2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces, this is not yet finished as multisampling is not used"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
78 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
85 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
86 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
95 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
137 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
138 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
170 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
177 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
178 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
179 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
180 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
182 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
183 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
184 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
185 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
186 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
187 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
188 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
190 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
191 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
192 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
193 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
194 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
195 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
196 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
199 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
201 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
203 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
205 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
207 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
208 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
209 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
210 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
211 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
212 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
213 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
214 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
215 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
217 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
218 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
220 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
222 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
224 extern cvar_t v_glslgamma;
226 extern qboolean v_flipped_state;
228 static struct r_bloomstate_s
233 int bloomwidth, bloomheight;
235 textype_t texturetype;
236 int viewfbo; // used to check if r_viewfbo cvar has changed
238 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
239 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
240 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
242 int screentexturewidth, screentextureheight;
243 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
245 int bloomtexturewidth, bloomtextureheight;
246 rtexture_t *texture_bloom;
248 // arrays for rendering the screen passes
249 float screentexcoord2f[8];
250 float bloomtexcoord2f[8];
251 float offsettexcoord2f[8];
253 r_viewport_t viewport;
257 r_waterstate_t r_waterstate;
259 /// shadow volume bsp struct with automatically growing nodes buffer
262 rtexture_t *r_texture_blanknormalmap;
263 rtexture_t *r_texture_white;
264 rtexture_t *r_texture_grey128;
265 rtexture_t *r_texture_black;
266 rtexture_t *r_texture_notexture;
267 rtexture_t *r_texture_whitecube;
268 rtexture_t *r_texture_normalizationcube;
269 rtexture_t *r_texture_fogattenuation;
270 rtexture_t *r_texture_fogheighttexture;
271 rtexture_t *r_texture_gammaramps;
272 unsigned int r_texture_gammaramps_serial;
273 //rtexture_t *r_texture_fogintensity;
274 rtexture_t *r_texture_reflectcube;
276 // TODO: hash lookups?
277 typedef struct cubemapinfo_s
284 int r_texture_numcubemaps;
285 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
287 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
288 unsigned int r_numqueries;
289 unsigned int r_maxqueries;
291 typedef struct r_qwskincache_s
293 char name[MAX_QPATH];
294 skinframe_t *skinframe;
298 static r_qwskincache_t *r_qwskincache;
299 static int r_qwskincache_size;
301 /// vertex coordinates for a quad that covers the screen exactly
302 extern const float r_screenvertex3f[12];
303 extern const float r_d3dscreenvertex3f[12];
304 const float r_screenvertex3f[12] =
311 const float r_d3dscreenvertex3f[12] =
319 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
322 for (i = 0;i < verts;i++)
333 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
336 for (i = 0;i < verts;i++)
346 // FIXME: move this to client?
349 if (gamemode == GAME_NEHAHRA)
351 Cvar_Set("gl_fogenable", "0");
352 Cvar_Set("gl_fogdensity", "0.2");
353 Cvar_Set("gl_fogred", "0.3");
354 Cvar_Set("gl_foggreen", "0.3");
355 Cvar_Set("gl_fogblue", "0.3");
357 r_refdef.fog_density = 0;
358 r_refdef.fog_red = 0;
359 r_refdef.fog_green = 0;
360 r_refdef.fog_blue = 0;
361 r_refdef.fog_alpha = 1;
362 r_refdef.fog_start = 0;
363 r_refdef.fog_end = 16384;
364 r_refdef.fog_height = 1<<30;
365 r_refdef.fog_fadedepth = 128;
366 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
369 static void R_BuildBlankTextures(void)
371 unsigned char data[4];
372 data[2] = 128; // normal X
373 data[1] = 128; // normal Y
374 data[0] = 255; // normal Z
375 data[3] = 128; // height
376 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 static void R_BuildNoTexture(void)
397 unsigned char pix[16][16][4];
398 // this makes a light grey/dark grey checkerboard texture
399 for (y = 0;y < 16;y++)
401 for (x = 0;x < 16;x++)
403 if ((y < 8) ^ (x < 8))
419 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
422 static void R_BuildWhiteCube(void)
424 unsigned char data[6*1*1*4];
425 memset(data, 255, sizeof(data));
426 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
429 static void R_BuildNormalizationCube(void)
433 vec_t s, t, intensity;
436 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
437 for (side = 0;side < 6;side++)
439 for (y = 0;y < NORMSIZE;y++)
441 for (x = 0;x < NORMSIZE;x++)
443 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
479 intensity = 127.0f / sqrt(DotProduct(v, v));
480 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
481 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
482 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
483 data[((side*64+y)*64+x)*4+3] = 255;
487 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
491 static void R_BuildFogTexture(void)
495 unsigned char data1[FOGWIDTH][4];
496 //unsigned char data2[FOGWIDTH][4];
499 r_refdef.fogmasktable_start = r_refdef.fog_start;
500 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
501 r_refdef.fogmasktable_range = r_refdef.fogrange;
502 r_refdef.fogmasktable_density = r_refdef.fog_density;
504 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
505 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
507 d = (x * r - r_refdef.fogmasktable_start);
508 if(developer_extra.integer)
509 Con_DPrintf("%f ", d);
511 if (r_fog_exp2.integer)
512 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
514 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
515 if(developer_extra.integer)
516 Con_DPrintf(" : %f ", alpha);
517 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
518 if(developer_extra.integer)
519 Con_DPrintf(" = %f\n", alpha);
520 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
523 for (x = 0;x < FOGWIDTH;x++)
525 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
530 //data2[x][0] = 255 - b;
531 //data2[x][1] = 255 - b;
532 //data2[x][2] = 255 - b;
535 if (r_texture_fogattenuation)
537 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
543 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
547 static void R_BuildFogHeightTexture(void)
549 unsigned char *inpixels;
557 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
558 if (r_refdef.fogheighttexturename[0])
559 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
562 r_refdef.fog_height_tablesize = 0;
563 if (r_texture_fogheighttexture)
564 R_FreeTexture(r_texture_fogheighttexture);
565 r_texture_fogheighttexture = NULL;
566 if (r_refdef.fog_height_table2d)
567 Mem_Free(r_refdef.fog_height_table2d);
568 r_refdef.fog_height_table2d = NULL;
569 if (r_refdef.fog_height_table1d)
570 Mem_Free(r_refdef.fog_height_table1d);
571 r_refdef.fog_height_table1d = NULL;
575 r_refdef.fog_height_tablesize = size;
576 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
577 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
578 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
580 // LordHavoc: now the magic - what is that table2d for? it is a cooked
581 // average fog color table accounting for every fog layer between a point
582 // and the camera. (Note: attenuation is handled separately!)
583 for (y = 0;y < size;y++)
585 for (x = 0;x < size;x++)
591 for (j = x;j <= y;j++)
593 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599 for (j = x;j >= y;j--)
601 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
606 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
609 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
612 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
615 //=======================================================================================================================================================
617 static const char *builtinshaderstring =
618 #include "shader_glsl.h"
621 const char *builtinhlslshaderstring =
622 #include "shader_hlsl.h"
625 char *glslshaderstring = NULL;
626 char *hlslshaderstring = NULL;
628 //=======================================================================================================================================================
630 typedef struct shaderpermutationinfo_s
635 shaderpermutationinfo_t;
637 typedef struct shadermodeinfo_s
639 const char *vertexfilename;
640 const char *geometryfilename;
641 const char *fragmentfilename;
647 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
648 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {"#define USEDIFFUSE\n", " diffuse"},
651 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
652 {"#define USEVIEWTINT\n", " viewtint"},
653 {"#define USECOLORMAPPING\n", " colormapping"},
654 {"#define USESATURATION\n", " saturation"},
655 {"#define USEFOGINSIDE\n", " foginside"},
656 {"#define USEFOGOUTSIDE\n", " fogoutside"},
657 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
658 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
659 {"#define USEGAMMARAMPS\n", " gammaramps"},
660 {"#define USECUBEFILTER\n", " cubefilter"},
661 {"#define USEGLOW\n", " glow"},
662 {"#define USEBLOOM\n", " bloom"},
663 {"#define USESPECULAR\n", " specular"},
664 {"#define USEPOSTPROCESSING\n", " postprocessing"},
665 {"#define USEREFLECTION\n", " reflection"},
666 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
667 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
668 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
669 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
670 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
671 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
672 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
673 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
674 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
675 {"#define USEALPHAKILL\n", " alphakill"},
676 {"#define USEREFLECTCUBE\n", " reflectcube"},
677 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
678 {"#define USEBOUNCEGRID\n", " bouncegrid"},
679 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
682 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
683 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
703 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
723 struct r_glsl_permutation_s;
724 typedef struct r_glsl_permutation_s
727 struct r_glsl_permutation_s *hashnext;
729 unsigned int permutation;
731 /// indicates if we have tried compiling this permutation already
733 /// 0 if compilation failed
735 // texture units assigned to each detected uniform
736 int tex_Texture_First;
737 int tex_Texture_Second;
738 int tex_Texture_GammaRamps;
739 int tex_Texture_Normal;
740 int tex_Texture_Color;
741 int tex_Texture_Gloss;
742 int tex_Texture_Glow;
743 int tex_Texture_SecondaryNormal;
744 int tex_Texture_SecondaryColor;
745 int tex_Texture_SecondaryGloss;
746 int tex_Texture_SecondaryGlow;
747 int tex_Texture_Pants;
748 int tex_Texture_Shirt;
749 int tex_Texture_FogHeightTexture;
750 int tex_Texture_FogMask;
751 int tex_Texture_Lightmap;
752 int tex_Texture_Deluxemap;
753 int tex_Texture_Attenuation;
754 int tex_Texture_Cube;
755 int tex_Texture_Refraction;
756 int tex_Texture_Reflection;
757 int tex_Texture_ShadowMap2D;
758 int tex_Texture_CubeProjection;
759 int tex_Texture_ScreenDepth;
760 int tex_Texture_ScreenNormalMap;
761 int tex_Texture_ScreenDiffuse;
762 int tex_Texture_ScreenSpecular;
763 int tex_Texture_ReflectMask;
764 int tex_Texture_ReflectCube;
765 int tex_Texture_BounceGrid;
766 /// locations of detected uniforms in program object, or -1 if not found
767 int loc_Texture_First;
768 int loc_Texture_Second;
769 int loc_Texture_GammaRamps;
770 int loc_Texture_Normal;
771 int loc_Texture_Color;
772 int loc_Texture_Gloss;
773 int loc_Texture_Glow;
774 int loc_Texture_SecondaryNormal;
775 int loc_Texture_SecondaryColor;
776 int loc_Texture_SecondaryGloss;
777 int loc_Texture_SecondaryGlow;
778 int loc_Texture_Pants;
779 int loc_Texture_Shirt;
780 int loc_Texture_FogHeightTexture;
781 int loc_Texture_FogMask;
782 int loc_Texture_Lightmap;
783 int loc_Texture_Deluxemap;
784 int loc_Texture_Attenuation;
785 int loc_Texture_Cube;
786 int loc_Texture_Refraction;
787 int loc_Texture_Reflection;
788 int loc_Texture_ShadowMap2D;
789 int loc_Texture_CubeProjection;
790 int loc_Texture_ScreenDepth;
791 int loc_Texture_ScreenNormalMap;
792 int loc_Texture_ScreenDiffuse;
793 int loc_Texture_ScreenSpecular;
794 int loc_Texture_ReflectMask;
795 int loc_Texture_ReflectCube;
796 int loc_Texture_BounceGrid;
798 int loc_BloomBlur_Parameters;
800 int loc_Color_Ambient;
801 int loc_Color_Diffuse;
802 int loc_Color_Specular;
806 int loc_DeferredColor_Ambient;
807 int loc_DeferredColor_Diffuse;
808 int loc_DeferredColor_Specular;
809 int loc_DeferredMod_Diffuse;
810 int loc_DeferredMod_Specular;
811 int loc_DistortScaleRefractReflect;
814 int loc_FogHeightFade;
816 int loc_FogPlaneViewDist;
817 int loc_FogRangeRecip;
820 int loc_LightPosition;
821 int loc_OffsetMapping_ScaleSteps;
823 int loc_ReflectColor;
824 int loc_ReflectFactor;
825 int loc_ReflectOffset;
826 int loc_RefractColor;
828 int loc_ScreenCenterRefractReflect;
829 int loc_ScreenScaleRefractReflect;
830 int loc_ScreenToDepth;
831 int loc_ShadowMap_Parameters;
832 int loc_ShadowMap_TextureScale;
833 int loc_SpecularPower;
838 int loc_ViewTintColor;
840 int loc_ModelToLight;
842 int loc_BackgroundTexMatrix;
843 int loc_ModelViewProjectionMatrix;
844 int loc_ModelViewMatrix;
845 int loc_PixelToScreenTexCoord;
846 int loc_ModelToReflectCube;
847 int loc_ShadowMapMatrix;
848 int loc_BloomColorSubtract;
849 int loc_NormalmapScrollBlend;
850 int loc_BounceGridMatrix;
851 int loc_BounceGridIntensity;
853 r_glsl_permutation_t;
855 #define SHADERPERMUTATION_HASHSIZE 256
858 // non-degradable "lightweight" shader parameters to keep the permutations simpler
859 // these can NOT degrade! only use for simple stuff
862 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
863 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
864 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
865 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
866 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
867 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
868 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
870 #define SHADERSTATICPARMS_COUNT 7
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
877 qboolean R_CompileShader_CheckStaticParms(void)
879 static int r_compileshader_staticparms_save[1];
880 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
881 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
884 if (r_glsl_saturation_redcompensate.integer)
885 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
886 if (r_glsl_vertextextureblend_usebothalphas.integer)
887 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
888 if (r_shadow_glossexact.integer)
889 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
890 if (r_glsl_postprocess.integer)
892 if (r_glsl_postprocess_uservec1_enable.integer)
893 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
894 if (r_glsl_postprocess_uservec2_enable.integer)
895 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
896 if (r_glsl_postprocess_uservec3_enable.integer)
897 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
898 if (r_glsl_postprocess_uservec4_enable.integer)
899 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
901 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
904 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
905 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
906 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
908 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
909 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
911 shaderstaticparms_count = 0;
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
920 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
923 /// information about each possible shader permutation
924 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
925 /// currently selected permutation
926 r_glsl_permutation_t *r_glsl_permutation;
927 /// storage for permutations linked in the hash table
928 memexpandablearray_t r_glsl_permutationarray;
930 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
932 //unsigned int hashdepth = 0;
933 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
934 r_glsl_permutation_t *p;
935 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
937 if (p->mode == mode && p->permutation == permutation)
939 //if (hashdepth > 10)
940 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
947 p->permutation = permutation;
948 p->hashnext = r_glsl_permutationhash[mode][hashindex];
949 r_glsl_permutationhash[mode][hashindex] = p;
950 //if (hashdepth > 10)
951 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
955 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
958 if (!filename || !filename[0])
960 if (!strcmp(filename, "glsl/default.glsl"))
962 if (!glslshaderstring)
964 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
965 if (glslshaderstring)
966 Con_DPrintf("Loading shaders from file %s...\n", filename);
968 glslshaderstring = (char *)builtinshaderstring;
970 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
971 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
974 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
977 if (printfromdisknotice)
978 Con_DPrintf("from disk %s... ", filename);
984 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
988 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
989 char *vertexstring, *geometrystring, *fragmentstring;
990 char permutationname[256];
991 int vertstrings_count = 0;
992 int geomstrings_count = 0;
993 int fragstrings_count = 0;
994 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1003 permutationname[0] = 0;
1004 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1005 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1006 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1008 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1010 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1011 if(vid.support.gl20shaders130)
1013 vertstrings_list[vertstrings_count++] = "#version 130\n";
1014 geomstrings_list[geomstrings_count++] = "#version 130\n";
1015 fragstrings_list[fragstrings_count++] = "#version 130\n";
1016 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1017 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1018 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1021 // the first pretext is which type of shader to compile as
1022 // (later these will all be bound together as a program object)
1023 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1024 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1025 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1027 // the second pretext is the mode (for example a light source)
1028 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1029 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1030 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1031 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1033 // now add all the permutation pretexts
1034 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1036 if (permutation & (1<<i))
1038 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1039 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1040 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1041 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1045 // keep line numbers correct
1046 vertstrings_list[vertstrings_count++] = "\n";
1047 geomstrings_list[geomstrings_count++] = "\n";
1048 fragstrings_list[fragstrings_count++] = "\n";
1053 R_CompileShader_AddStaticParms(mode, permutation);
1054 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1055 vertstrings_count += shaderstaticparms_count;
1056 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1057 geomstrings_count += shaderstaticparms_count;
1058 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059 fragstrings_count += shaderstaticparms_count;
1061 // now append the shader text itself
1062 vertstrings_list[vertstrings_count++] = vertexstring;
1063 geomstrings_list[geomstrings_count++] = geometrystring;
1064 fragstrings_list[fragstrings_count++] = fragmentstring;
1066 // if any sources were NULL, clear the respective list
1068 vertstrings_count = 0;
1069 if (!geometrystring)
1070 geomstrings_count = 0;
1071 if (!fragmentstring)
1072 fragstrings_count = 0;
1074 // compile the shader program
1075 if (vertstrings_count + geomstrings_count + fragstrings_count)
1076 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1080 qglUseProgram(p->program);CHECKGLERROR
1081 // look up all the uniform variable names we care about, so we don't
1082 // have to look them up every time we set them
1084 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1085 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1086 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1087 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1088 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1089 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1090 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1091 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1092 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1093 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1094 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1095 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1096 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1097 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1098 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1099 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1100 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1101 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1102 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1103 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1104 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1105 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1106 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1107 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1108 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1109 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1110 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1111 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1112 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1113 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1114 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1115 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1116 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1117 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1118 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1119 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1120 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1121 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1122 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1123 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1124 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1125 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1126 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1127 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1128 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1129 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1130 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1131 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1132 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1133 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1134 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1135 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1136 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1137 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1138 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1139 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1140 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1141 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1142 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1143 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1144 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1145 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1146 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1147 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1148 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1149 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1150 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1151 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1152 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1153 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1154 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1155 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1156 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1157 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1158 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1159 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1160 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1161 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1162 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1163 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1164 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1165 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1166 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1167 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1168 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1169 // initialize the samplers to refer to the texture units we use
1170 p->tex_Texture_First = -1;
1171 p->tex_Texture_Second = -1;
1172 p->tex_Texture_GammaRamps = -1;
1173 p->tex_Texture_Normal = -1;
1174 p->tex_Texture_Color = -1;
1175 p->tex_Texture_Gloss = -1;
1176 p->tex_Texture_Glow = -1;
1177 p->tex_Texture_SecondaryNormal = -1;
1178 p->tex_Texture_SecondaryColor = -1;
1179 p->tex_Texture_SecondaryGloss = -1;
1180 p->tex_Texture_SecondaryGlow = -1;
1181 p->tex_Texture_Pants = -1;
1182 p->tex_Texture_Shirt = -1;
1183 p->tex_Texture_FogHeightTexture = -1;
1184 p->tex_Texture_FogMask = -1;
1185 p->tex_Texture_Lightmap = -1;
1186 p->tex_Texture_Deluxemap = -1;
1187 p->tex_Texture_Attenuation = -1;
1188 p->tex_Texture_Cube = -1;
1189 p->tex_Texture_Refraction = -1;
1190 p->tex_Texture_Reflection = -1;
1191 p->tex_Texture_ShadowMap2D = -1;
1192 p->tex_Texture_CubeProjection = -1;
1193 p->tex_Texture_ScreenDepth = -1;
1194 p->tex_Texture_ScreenNormalMap = -1;
1195 p->tex_Texture_ScreenDiffuse = -1;
1196 p->tex_Texture_ScreenSpecular = -1;
1197 p->tex_Texture_ReflectMask = -1;
1198 p->tex_Texture_ReflectCube = -1;
1199 p->tex_Texture_BounceGrid = -1;
1201 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1202 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1203 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1204 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1205 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1206 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1207 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1208 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1209 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1211 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1212 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1213 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1214 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1215 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1216 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1217 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1218 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1219 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1220 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1221 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1222 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1223 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1224 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1225 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1227 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1228 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1229 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1230 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1232 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1235 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1239 Mem_Free(vertexstring);
1241 Mem_Free(geometrystring);
1243 Mem_Free(fragmentstring);
1246 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1248 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1249 if (r_glsl_permutation != perm)
1251 r_glsl_permutation = perm;
1252 if (!r_glsl_permutation->program)
1254 if (!r_glsl_permutation->compiled)
1255 R_GLSL_CompilePermutation(perm, mode, permutation);
1256 if (!r_glsl_permutation->program)
1258 // remove features until we find a valid permutation
1260 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1262 // reduce i more quickly whenever it would not remove any bits
1263 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1264 if (!(permutation & j))
1267 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1268 if (!r_glsl_permutation->compiled)
1269 R_GLSL_CompilePermutation(perm, mode, permutation);
1270 if (r_glsl_permutation->program)
1273 if (i >= SHADERPERMUTATION_COUNT)
1275 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1276 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1277 qglUseProgram(0);CHECKGLERROR
1278 return; // no bit left to clear, entire mode is broken
1283 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1285 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1286 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1287 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1294 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1295 extern D3DCAPS9 vid_d3d9caps;
1298 struct r_hlsl_permutation_s;
1299 typedef struct r_hlsl_permutation_s
1301 /// hash lookup data
1302 struct r_hlsl_permutation_s *hashnext;
1304 unsigned int permutation;
1306 /// indicates if we have tried compiling this permutation already
1308 /// NULL if compilation failed
1309 IDirect3DVertexShader9 *vertexshader;
1310 IDirect3DPixelShader9 *pixelshader;
1312 r_hlsl_permutation_t;
1314 typedef enum D3DVSREGISTER_e
1316 D3DVSREGISTER_TexMatrix = 0, // float4x4
1317 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1318 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1319 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1320 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1321 D3DVSREGISTER_ModelToLight = 20, // float4x4
1322 D3DVSREGISTER_EyePosition = 24,
1323 D3DVSREGISTER_FogPlane = 25,
1324 D3DVSREGISTER_LightDir = 26,
1325 D3DVSREGISTER_LightPosition = 27,
1329 typedef enum D3DPSREGISTER_e
1331 D3DPSREGISTER_Alpha = 0,
1332 D3DPSREGISTER_BloomBlur_Parameters = 1,
1333 D3DPSREGISTER_ClientTime = 2,
1334 D3DPSREGISTER_Color_Ambient = 3,
1335 D3DPSREGISTER_Color_Diffuse = 4,
1336 D3DPSREGISTER_Color_Specular = 5,
1337 D3DPSREGISTER_Color_Glow = 6,
1338 D3DPSREGISTER_Color_Pants = 7,
1339 D3DPSREGISTER_Color_Shirt = 8,
1340 D3DPSREGISTER_DeferredColor_Ambient = 9,
1341 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1342 D3DPSREGISTER_DeferredColor_Specular = 11,
1343 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1344 D3DPSREGISTER_DeferredMod_Specular = 13,
1345 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1346 D3DPSREGISTER_EyePosition = 15, // unused
1347 D3DPSREGISTER_FogColor = 16,
1348 D3DPSREGISTER_FogHeightFade = 17,
1349 D3DPSREGISTER_FogPlane = 18,
1350 D3DPSREGISTER_FogPlaneViewDist = 19,
1351 D3DPSREGISTER_FogRangeRecip = 20,
1352 D3DPSREGISTER_LightColor = 21,
1353 D3DPSREGISTER_LightDir = 22, // unused
1354 D3DPSREGISTER_LightPosition = 23,
1355 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1356 D3DPSREGISTER_PixelSize = 25,
1357 D3DPSREGISTER_ReflectColor = 26,
1358 D3DPSREGISTER_ReflectFactor = 27,
1359 D3DPSREGISTER_ReflectOffset = 28,
1360 D3DPSREGISTER_RefractColor = 29,
1361 D3DPSREGISTER_Saturation = 30,
1362 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1363 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1364 D3DPSREGISTER_ScreenToDepth = 33,
1365 D3DPSREGISTER_ShadowMap_Parameters = 34,
1366 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1367 D3DPSREGISTER_SpecularPower = 36,
1368 D3DPSREGISTER_UserVec1 = 37,
1369 D3DPSREGISTER_UserVec2 = 38,
1370 D3DPSREGISTER_UserVec3 = 39,
1371 D3DPSREGISTER_UserVec4 = 40,
1372 D3DPSREGISTER_ViewTintColor = 41,
1373 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1374 D3DPSREGISTER_BloomColorSubtract = 43,
1375 D3DPSREGISTER_ViewToLight = 44, // float4x4
1376 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1377 D3DPSREGISTER_NormalmapScrollBlend = 52,
1382 /// information about each possible shader permutation
1383 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1384 /// currently selected permutation
1385 r_hlsl_permutation_t *r_hlsl_permutation;
1386 /// storage for permutations linked in the hash table
1387 memexpandablearray_t r_hlsl_permutationarray;
1389 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1391 //unsigned int hashdepth = 0;
1392 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1393 r_hlsl_permutation_t *p;
1394 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1396 if (p->mode == mode && p->permutation == permutation)
1398 //if (hashdepth > 10)
1399 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1404 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1406 p->permutation = permutation;
1407 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1408 r_hlsl_permutationhash[mode][hashindex] = p;
1409 //if (hashdepth > 10)
1410 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1414 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1417 if (!filename || !filename[0])
1419 if (!strcmp(filename, "hlsl/default.hlsl"))
1421 if (!hlslshaderstring)
1423 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1424 if (hlslshaderstring)
1425 Con_DPrintf("Loading shaders from file %s...\n", filename);
1427 hlslshaderstring = (char *)builtinhlslshaderstring;
1429 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1430 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1431 return shaderstring;
1433 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1436 if (printfromdisknotice)
1437 Con_DPrintf("from disk %s... ", filename);
1438 return shaderstring;
1440 return shaderstring;
1444 //#include <d3dx9shader.h>
1445 //#include <d3dx9mesh.h>
1447 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1449 DWORD *vsbin = NULL;
1450 DWORD *psbin = NULL;
1451 fs_offset_t vsbinsize;
1452 fs_offset_t psbinsize;
1453 // IDirect3DVertexShader9 *vs = NULL;
1454 // IDirect3DPixelShader9 *ps = NULL;
1455 ID3DXBuffer *vslog = NULL;
1456 ID3DXBuffer *vsbuffer = NULL;
1457 ID3DXConstantTable *vsconstanttable = NULL;
1458 ID3DXBuffer *pslog = NULL;
1459 ID3DXBuffer *psbuffer = NULL;
1460 ID3DXConstantTable *psconstanttable = NULL;
1463 char temp[MAX_INPUTLINE];
1464 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1465 qboolean debugshader = gl_paranoid.integer != 0;
1466 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1470 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1471 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1473 if ((!vsbin && vertstring) || (!psbin && fragstring))
1475 const char* dllnames_d3dx9 [] =
1499 dllhandle_t d3dx9_dll = NULL;
1500 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1501 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1502 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1503 dllfunction_t d3dx9_dllfuncs[] =
1505 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1506 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1507 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1510 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1512 DWORD shaderflags = 0;
1514 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1515 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1516 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1517 if (vertstring && vertstring[0])
1521 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1522 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1523 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1524 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1527 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1530 vsbinsize = vsbuffer->GetBufferSize();
1531 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1532 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1533 vsbuffer->Release();
1537 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1538 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1542 if (fragstring && fragstring[0])
1546 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1547 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1548 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1549 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1552 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1555 psbinsize = psbuffer->GetBufferSize();
1556 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1557 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1558 psbuffer->Release();
1562 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1563 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1567 Sys_UnloadLibrary(&d3dx9_dll);
1570 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1574 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1575 if (FAILED(vsresult))
1576 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1577 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1578 if (FAILED(psresult))
1579 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1581 // free the shader data
1582 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1583 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1586 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1589 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1590 int vertstring_length = 0;
1591 int geomstring_length = 0;
1592 int fragstring_length = 0;
1594 char *vertexstring, *geometrystring, *fragmentstring;
1595 char *vertstring, *geomstring, *fragstring;
1596 char permutationname[256];
1597 char cachename[256];
1598 int vertstrings_count = 0;
1599 int geomstrings_count = 0;
1600 int fragstrings_count = 0;
1601 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608 p->vertexshader = NULL;
1609 p->pixelshader = NULL;
1611 permutationname[0] = 0;
1613 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1614 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1615 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1617 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1618 strlcat(cachename, "hlsl/", sizeof(cachename));
1620 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1621 vertstrings_count = 0;
1622 geomstrings_count = 0;
1623 fragstrings_count = 0;
1624 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1625 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1626 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1628 // the first pretext is which type of shader to compile as
1629 // (later these will all be bound together as a program object)
1630 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1631 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1632 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1634 // the second pretext is the mode (for example a light source)
1635 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1636 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1637 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1638 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1639 strlcat(cachename, modeinfo->name, sizeof(cachename));
1641 // now add all the permutation pretexts
1642 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1644 if (permutation & (1<<i))
1646 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1647 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1648 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1649 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1650 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1654 // keep line numbers correct
1655 vertstrings_list[vertstrings_count++] = "\n";
1656 geomstrings_list[geomstrings_count++] = "\n";
1657 fragstrings_list[fragstrings_count++] = "\n";
1662 R_CompileShader_AddStaticParms(mode, permutation);
1663 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1664 vertstrings_count += shaderstaticparms_count;
1665 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1666 geomstrings_count += shaderstaticparms_count;
1667 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1668 fragstrings_count += shaderstaticparms_count;
1670 // replace spaces in the cachename with _ characters
1671 for (i = 0;cachename[i];i++)
1672 if (cachename[i] == ' ')
1675 // now append the shader text itself
1676 vertstrings_list[vertstrings_count++] = vertexstring;
1677 geomstrings_list[geomstrings_count++] = geometrystring;
1678 fragstrings_list[fragstrings_count++] = fragmentstring;
1680 // if any sources were NULL, clear the respective list
1682 vertstrings_count = 0;
1683 if (!geometrystring)
1684 geomstrings_count = 0;
1685 if (!fragmentstring)
1686 fragstrings_count = 0;
1688 vertstring_length = 0;
1689 for (i = 0;i < vertstrings_count;i++)
1690 vertstring_length += strlen(vertstrings_list[i]);
1691 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1692 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1693 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1695 geomstring_length = 0;
1696 for (i = 0;i < geomstrings_count;i++)
1697 geomstring_length += strlen(geomstrings_list[i]);
1698 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1699 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1700 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1702 fragstring_length = 0;
1703 for (i = 0;i < fragstrings_count;i++)
1704 fragstring_length += strlen(fragstrings_list[i]);
1705 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1706 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1707 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1709 // try to load the cached shader, or generate one
1710 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1712 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1713 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1715 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1719 Mem_Free(vertstring);
1721 Mem_Free(geomstring);
1723 Mem_Free(fragstring);
1725 Mem_Free(vertexstring);
1727 Mem_Free(geometrystring);
1729 Mem_Free(fragmentstring);
1732 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1737 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1739 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1740 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1741 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1742 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1743 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1744 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1746 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1748 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1749 if (r_hlsl_permutation != perm)
1751 r_hlsl_permutation = perm;
1752 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1754 if (!r_hlsl_permutation->compiled)
1755 R_HLSL_CompilePermutation(perm, mode, permutation);
1756 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1758 // remove features until we find a valid permutation
1760 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1762 // reduce i more quickly whenever it would not remove any bits
1763 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1764 if (!(permutation & j))
1767 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1768 if (!r_hlsl_permutation->compiled)
1769 R_HLSL_CompilePermutation(perm, mode, permutation);
1770 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1773 if (i >= SHADERPERMUTATION_COUNT)
1775 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1776 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1777 return; // no bit left to clear, entire mode is broken
1781 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1782 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1784 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1785 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1786 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1790 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1792 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1793 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1794 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1795 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1798 void R_GLSL_Restart_f(void)
1800 unsigned int i, limit;
1801 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1802 Mem_Free(glslshaderstring);
1803 glslshaderstring = NULL;
1804 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1805 Mem_Free(hlslshaderstring);
1806 hlslshaderstring = NULL;
1807 switch(vid.renderpath)
1809 case RENDERPATH_D3D9:
1812 r_hlsl_permutation_t *p;
1813 r_hlsl_permutation = NULL;
1814 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1815 for (i = 0;i < limit;i++)
1817 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1819 if (p->vertexshader)
1820 IDirect3DVertexShader9_Release(p->vertexshader);
1822 IDirect3DPixelShader9_Release(p->pixelshader);
1823 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1826 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1830 case RENDERPATH_D3D10:
1831 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1833 case RENDERPATH_D3D11:
1834 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1836 case RENDERPATH_GL20:
1837 case RENDERPATH_GLES2:
1839 r_glsl_permutation_t *p;
1840 r_glsl_permutation = NULL;
1841 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1842 for (i = 0;i < limit;i++)
1844 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1846 GL_Backend_FreeProgram(p->program);
1847 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1850 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1853 case RENDERPATH_GL11:
1854 case RENDERPATH_GL13:
1855 case RENDERPATH_GLES1:
1857 case RENDERPATH_SOFT:
1862 void R_GLSL_DumpShader_f(void)
1867 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1870 FS_Print(file, "/* The engine may define the following macros:\n");
1871 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1872 for (i = 0;i < SHADERMODE_COUNT;i++)
1873 FS_Print(file, glslshadermodeinfo[i].pretext);
1874 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1875 FS_Print(file, shaderpermutationinfo[i].pretext);
1876 FS_Print(file, "*/\n");
1877 FS_Print(file, builtinshaderstring);
1879 Con_Printf("glsl/default.glsl written\n");
1882 Con_Printf("failed to write to glsl/default.glsl\n");
1884 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1887 FS_Print(file, "/* The engine may define the following macros:\n");
1888 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889 for (i = 0;i < SHADERMODE_COUNT;i++)
1890 FS_Print(file, hlslshadermodeinfo[i].pretext);
1891 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892 FS_Print(file, shaderpermutationinfo[i].pretext);
1893 FS_Print(file, "*/\n");
1894 FS_Print(file, builtinhlslshaderstring);
1896 Con_Printf("hlsl/default.hlsl written\n");
1899 Con_Printf("failed to write to hlsl/default.hlsl\n");
1902 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1905 texturemode = GL_MODULATE;
1906 switch (vid.renderpath)
1908 case RENDERPATH_D3D9:
1910 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1911 R_Mesh_TexBind(GL20TU_FIRST , first );
1912 R_Mesh_TexBind(GL20TU_SECOND, second);
1915 case RENDERPATH_D3D10:
1916 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918 case RENDERPATH_D3D11:
1919 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1921 case RENDERPATH_GL20:
1922 case RENDERPATH_GLES2:
1923 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1924 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1925 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1927 case RENDERPATH_GL13:
1928 case RENDERPATH_GLES1:
1929 R_Mesh_TexBind(0, first );
1930 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1931 R_Mesh_TexBind(1, second);
1933 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1935 case RENDERPATH_GL11:
1936 R_Mesh_TexBind(0, first );
1938 case RENDERPATH_SOFT:
1939 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1940 R_Mesh_TexBind(GL20TU_FIRST , first );
1941 R_Mesh_TexBind(GL20TU_SECOND, second);
1946 void R_SetupShader_DepthOrShadow(void)
1948 switch (vid.renderpath)
1950 case RENDERPATH_D3D9:
1952 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1955 case RENDERPATH_D3D10:
1956 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958 case RENDERPATH_D3D11:
1959 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961 case RENDERPATH_GL20:
1962 case RENDERPATH_GLES2:
1963 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1965 case RENDERPATH_GL13:
1966 case RENDERPATH_GLES1:
1967 R_Mesh_TexBind(0, 0);
1968 R_Mesh_TexBind(1, 0);
1970 case RENDERPATH_GL11:
1971 R_Mesh_TexBind(0, 0);
1973 case RENDERPATH_SOFT:
1974 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1979 void R_SetupShader_ShowDepth(void)
1981 switch (vid.renderpath)
1983 case RENDERPATH_D3D9:
1985 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1988 case RENDERPATH_D3D10:
1989 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1991 case RENDERPATH_D3D11:
1992 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1994 case RENDERPATH_GL20:
1995 case RENDERPATH_GLES2:
1996 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1998 case RENDERPATH_GL13:
1999 case RENDERPATH_GLES1:
2001 case RENDERPATH_GL11:
2003 case RENDERPATH_SOFT:
2004 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2009 extern qboolean r_shadow_usingdeferredprepass;
2010 extern cvar_t r_shadow_deferred_8bitrange;
2011 extern rtexture_t *r_shadow_attenuationgradienttexture;
2012 extern rtexture_t *r_shadow_attenuation2dtexture;
2013 extern rtexture_t *r_shadow_attenuation3dtexture;
2014 extern qboolean r_shadow_usingshadowmap2d;
2015 extern qboolean r_shadow_usingshadowmaportho;
2016 extern float r_shadow_shadowmap_texturescale[2];
2017 extern float r_shadow_shadowmap_parameters[4];
2018 extern qboolean r_shadow_shadowmapvsdct;
2019 extern qboolean r_shadow_shadowmapsampler;
2020 extern int r_shadow_shadowmappcf;
2021 extern rtexture_t *r_shadow_shadowmap2dtexture;
2022 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2023 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2024 extern matrix4x4_t r_shadow_shadowmapmatrix;
2025 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2026 extern int r_shadow_prepass_width;
2027 extern int r_shadow_prepass_height;
2028 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2029 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2030 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2031 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2032 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2034 #define BLENDFUNC_ALLOWS_COLORMOD 1
2035 #define BLENDFUNC_ALLOWS_FOG 2
2036 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2037 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2038 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2039 static int R_BlendFuncFlags(int src, int dst)
2043 // a blendfunc allows colormod if:
2044 // a) it can never keep the destination pixel invariant, or
2045 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2046 // this is to prevent unintended side effects from colormod
2048 // a blendfunc allows fog if:
2049 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2050 // this is to prevent unintended side effects from fog
2052 // these checks are the output of fogeval.pl
2054 r |= BLENDFUNC_ALLOWS_COLORMOD;
2055 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2057 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2058 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2059 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2062 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2063 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2064 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2065 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2066 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2067 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2068 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2069 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2070 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2072 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2073 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2074 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2075 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2080 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
2082 // select a permutation of the lighting shader appropriate to this
2083 // combination of texture, entity, light source, and fogging, only use the
2084 // minimum features necessary to avoid wasting rendering time in the
2085 // fragment shader on features that are not being used
2086 unsigned int permutation = 0;
2087 unsigned int mode = 0;
2089 static float dummy_colormod[3] = {1, 1, 1};
2090 float *colormod = rsurface.colormod;
2092 matrix4x4_t tempmatrix;
2093 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2094 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2095 permutation |= SHADERPERMUTATION_ALPHAKILL;
2096 // Alpha to Coverage
2097 // fixme: move to gl_backend
2098 if (vid_multisampling.integer && r_transparent_alphatocoverage.integer)
2100 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2102 qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2106 qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
2109 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2110 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2111 if (rsurfacepass == RSURFPASS_BACKGROUND)
2113 // distorted background
2114 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2116 mode = SHADERMODE_WATER;
2117 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2119 // this is the right thing to do for wateralpha
2120 GL_BlendFunc(GL_ONE, GL_ZERO);
2121 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2125 // this is the right thing to do for entity alpha
2126 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2127 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2130 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2132 mode = SHADERMODE_REFRACTION;
2133 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2134 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2138 mode = SHADERMODE_GENERIC;
2139 permutation |= SHADERPERMUTATION_DIFFUSE;
2140 GL_BlendFunc(GL_ONE, GL_ZERO);
2141 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2144 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2146 if (r_glsl_offsetmapping.integer)
2148 switch(rsurface.texture->offsetmapping)
2150 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2151 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2152 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2153 case OFFSETMAPPING_OFF: break;
2156 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2157 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2158 // normalmap (deferred prepass), may use alpha test on diffuse
2159 mode = SHADERMODE_DEFERREDGEOMETRY;
2160 GL_BlendFunc(GL_ONE, GL_ZERO);
2161 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2163 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2165 if (r_glsl_offsetmapping.integer)
2167 switch(rsurface.texture->offsetmapping)
2169 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2170 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2171 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2172 case OFFSETMAPPING_OFF: break;
2175 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2176 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2178 mode = SHADERMODE_LIGHTSOURCE;
2179 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2180 permutation |= SHADERPERMUTATION_CUBEFILTER;
2181 if (diffusescale > 0)
2182 permutation |= SHADERPERMUTATION_DIFFUSE;
2183 if (specularscale > 0)
2184 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2185 if (r_refdef.fogenabled)
2186 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2187 if (rsurface.texture->colormapping)
2188 permutation |= SHADERPERMUTATION_COLORMAPPING;
2189 if (r_shadow_usingshadowmap2d)
2191 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2192 if(r_shadow_shadowmapvsdct)
2193 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2195 if (r_shadow_shadowmapsampler)
2196 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2197 if (r_shadow_shadowmappcf > 1)
2198 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2199 else if (r_shadow_shadowmappcf)
2200 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2202 if (rsurface.texture->reflectmasktexture)
2203 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2204 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2205 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2207 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2209 if (r_glsl_offsetmapping.integer)
2211 switch(rsurface.texture->offsetmapping)
2213 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2214 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2215 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2216 case OFFSETMAPPING_OFF: break;
2219 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2220 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2221 // unshaded geometry (fullbright or ambient model lighting)
2222 mode = SHADERMODE_FLATCOLOR;
2223 ambientscale = diffusescale = specularscale = 0;
2224 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2225 permutation |= SHADERPERMUTATION_GLOW;
2226 if (r_refdef.fogenabled)
2227 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2228 if (rsurface.texture->colormapping)
2229 permutation |= SHADERPERMUTATION_COLORMAPPING;
2230 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2232 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2233 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2235 if (r_shadow_shadowmapsampler)
2236 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2237 if (r_shadow_shadowmappcf > 1)
2238 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2239 else if (r_shadow_shadowmappcf)
2240 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2242 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2243 permutation |= SHADERPERMUTATION_REFLECTION;
2244 if (rsurface.texture->reflectmasktexture)
2245 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2246 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2247 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2249 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2251 if (r_glsl_offsetmapping.integer)
2253 switch(rsurface.texture->offsetmapping)
2255 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2256 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2258 case OFFSETMAPPING_OFF: break;
2261 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2262 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2263 // directional model lighting
2264 mode = SHADERMODE_LIGHTDIRECTION;
2265 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2266 permutation |= SHADERPERMUTATION_GLOW;
2267 permutation |= SHADERPERMUTATION_DIFFUSE;
2268 if (specularscale > 0)
2269 permutation |= SHADERPERMUTATION_SPECULAR;
2270 if (r_refdef.fogenabled)
2271 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2272 if (rsurface.texture->colormapping)
2273 permutation |= SHADERPERMUTATION_COLORMAPPING;
2274 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2276 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2277 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2279 if (r_shadow_shadowmapsampler)
2280 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2281 if (r_shadow_shadowmappcf > 1)
2282 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2283 else if (r_shadow_shadowmappcf)
2284 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2286 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2287 permutation |= SHADERPERMUTATION_REFLECTION;
2288 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2289 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2290 if (rsurface.texture->reflectmasktexture)
2291 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2292 if (r_shadow_bouncegridtexture)
2294 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2295 if (r_shadow_bouncegriddirectional)
2296 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2298 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2299 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2301 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2303 if (r_glsl_offsetmapping.integer)
2305 switch(rsurface.texture->offsetmapping)
2307 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2308 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2309 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2310 case OFFSETMAPPING_OFF: break;
2313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2314 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2315 // ambient model lighting
2316 mode = SHADERMODE_LIGHTDIRECTION;
2317 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2318 permutation |= SHADERPERMUTATION_GLOW;
2319 if (r_refdef.fogenabled)
2320 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2321 if (rsurface.texture->colormapping)
2322 permutation |= SHADERPERMUTATION_COLORMAPPING;
2323 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2325 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2326 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2328 if (r_shadow_shadowmapsampler)
2329 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2330 if (r_shadow_shadowmappcf > 1)
2331 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2332 else if (r_shadow_shadowmappcf)
2333 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2335 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2336 permutation |= SHADERPERMUTATION_REFLECTION;
2337 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2338 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2339 if (rsurface.texture->reflectmasktexture)
2340 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2341 if (r_shadow_bouncegridtexture)
2343 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2344 if (r_shadow_bouncegriddirectional)
2345 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2347 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2348 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352 if (r_glsl_offsetmapping.integer)
2354 switch(rsurface.texture->offsetmapping)
2356 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2357 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2358 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2359 case OFFSETMAPPING_OFF: break;
2362 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2363 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2365 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2366 permutation |= SHADERPERMUTATION_GLOW;
2367 if (r_refdef.fogenabled)
2368 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2369 if (rsurface.texture->colormapping)
2370 permutation |= SHADERPERMUTATION_COLORMAPPING;
2371 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2373 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2374 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2376 if (r_shadow_shadowmapsampler)
2377 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2378 if (r_shadow_shadowmappcf > 1)
2379 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2380 else if (r_shadow_shadowmappcf)
2381 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2383 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2384 permutation |= SHADERPERMUTATION_REFLECTION;
2385 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2386 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2387 if (rsurface.texture->reflectmasktexture)
2388 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2389 if (FAKELIGHT_ENABLED)
2391 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2392 mode = SHADERMODE_FAKELIGHT;
2393 permutation |= SHADERPERMUTATION_DIFFUSE;
2394 if (specularscale > 0)
2395 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2397 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2399 // deluxemapping (light direction texture)
2400 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2401 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2403 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2404 permutation |= SHADERPERMUTATION_DIFFUSE;
2405 if (specularscale > 0)
2406 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2408 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2410 // fake deluxemapping (uniform light direction in tangentspace)
2411 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2412 permutation |= SHADERPERMUTATION_DIFFUSE;
2413 if (specularscale > 0)
2414 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2416 else if (rsurface.uselightmaptexture)
2418 // ordinary lightmapping (q1bsp, q3bsp)
2419 mode = SHADERMODE_LIGHTMAP;
2423 // ordinary vertex coloring (q3bsp)
2424 mode = SHADERMODE_VERTEXCOLOR;
2426 if (r_shadow_bouncegridtexture)
2428 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2429 if (r_shadow_bouncegriddirectional)
2430 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2432 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2433 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2436 colormod = dummy_colormod;
2437 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2438 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2439 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2440 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2441 switch(vid.renderpath)
2443 case RENDERPATH_D3D9:
2445 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);
2446 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2447 R_SetupShader_SetPermutationHLSL(mode, permutation);
2448 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2449 if (mode == SHADERMODE_LIGHTSOURCE)
2451 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2452 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2456 if (mode == SHADERMODE_LIGHTDIRECTION)
2458 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2461 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2462 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2463 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2464 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2465 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2467 if (mode == SHADERMODE_LIGHTSOURCE)
2469 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2470 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2471 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2472 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2473 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2475 // additive passes are only darkened by fog, not tinted
2476 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2477 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2481 if (mode == SHADERMODE_FLATCOLOR)
2483 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2485 else if (mode == SHADERMODE_LIGHTDIRECTION)
2487 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]);
2488 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2489 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);
2490 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);
2491 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2492 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2493 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2497 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2498 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2499 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);
2500 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);
2501 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2503 // additive passes are only darkened by fog, not tinted
2504 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2505 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2507 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2508 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);
2509 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2510 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2511 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2512 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2513 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2514 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2515 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2516 if (mode == SHADERMODE_WATER)
2517 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2519 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2520 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2521 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2522 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));
2523 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2524 if (rsurface.texture->pantstexture)
2525 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2527 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2528 if (rsurface.texture->shirttexture)
2529 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2531 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2532 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2533 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2534 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2535 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2536 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2537 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2538 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2539 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2540 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2542 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2543 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2545 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2546 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2547 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2548 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2549 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2550 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2551 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2552 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2553 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2554 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2555 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2556 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2557 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2558 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2559 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2560 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2561 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2562 if (rsurfacepass == RSURFPASS_BACKGROUND)
2564 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2565 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2566 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2570 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2572 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2573 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2574 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2575 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2576 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2578 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2579 if (rsurface.rtlight)
2581 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2582 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2587 case RENDERPATH_D3D10:
2588 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2590 case RENDERPATH_D3D11:
2591 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2593 case RENDERPATH_GL20:
2594 case RENDERPATH_GLES2:
2595 if (!vid.useinterleavedarrays)
2597 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);
2598 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2599 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2600 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2601 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2602 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2603 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2604 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2608 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);
2609 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2611 R_SetupShader_SetPermutationGLSL(mode, permutation);
2612 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2613 if (mode == SHADERMODE_LIGHTSOURCE)
2615 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2616 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2617 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2618 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2619 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2620 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);
2622 // additive passes are only darkened by fog, not tinted
2623 if (r_glsl_permutation->loc_FogColor >= 0)
2624 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2625 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2629 if (mode == SHADERMODE_FLATCOLOR)
2631 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2633 else if (mode == SHADERMODE_LIGHTDIRECTION)
2635 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]);
2636 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]);
2637 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);
2638 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);
2639 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);
2640 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]);
2641 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]);
2645 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]);
2646 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]);
2647 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);
2648 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);
2649 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);
2651 // additive passes are only darkened by fog, not tinted
2652 if (r_glsl_permutation->loc_FogColor >= 0)
2654 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2655 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2657 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2659 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);
2660 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]);
2661 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]);
2662 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]);
2663 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]);
2664 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2665 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2666 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2667 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]);
2669 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2670 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2671 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2672 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]);
2673 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]);
2675 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2676 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));
2677 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2678 if (r_glsl_permutation->loc_Color_Pants >= 0)
2680 if (rsurface.texture->pantstexture)
2681 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2683 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2685 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2687 if (rsurface.texture->shirttexture)
2688 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2690 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2692 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]);
2693 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2694 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2695 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2696 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2697 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2698 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2699 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2700 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2702 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]);
2703 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2704 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);}
2705 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2707 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2708 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2709 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2710 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2711 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2712 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2713 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2714 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2715 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2716 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2717 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2718 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2719 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2720 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2721 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);
2722 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2723 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2724 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2725 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2726 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2727 if (rsurfacepass == RSURFPASS_BACKGROUND)
2729 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);
2730 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);
2731 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);
2735 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);
2737 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2738 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2739 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2740 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2741 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2743 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2744 if (rsurface.rtlight)
2746 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2747 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2750 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2753 case RENDERPATH_GL11:
2754 case RENDERPATH_GL13:
2755 case RENDERPATH_GLES1:
2757 case RENDERPATH_SOFT:
2758 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);
2759 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2760 R_SetupShader_SetPermutationSoft(mode, permutation);
2761 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2762 if (mode == SHADERMODE_LIGHTSOURCE)
2764 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2765 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2767 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2768 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2769 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2771 // additive passes are only darkened by fog, not tinted
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2773 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2777 if (mode == SHADERMODE_FLATCOLOR)
2779 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2781 else if (mode == SHADERMODE_LIGHTDIRECTION)
2783 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]);
2784 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2785 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);
2786 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);
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2788 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]);
2789 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2793 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2794 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2795 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);
2796 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);
2797 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2799 // additive passes are only darkened by fog, not tinted
2800 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2801 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2803 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2804 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);
2805 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2806 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2807 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]);
2808 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]);
2809 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2810 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2811 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2812 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2814 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2815 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2816 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2817 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2818 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]);
2820 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2821 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));
2822 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2823 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2825 if (rsurface.texture->pantstexture)
2826 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2828 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2830 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2832 if (rsurface.texture->shirttexture)
2833 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2835 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2837 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2838 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2839 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2840 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2841 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2842 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2843 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2844 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2845 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2847 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2848 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2850 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2851 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2852 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2853 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2854 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2855 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2856 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2857 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2858 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2859 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2860 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2861 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2862 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2863 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2864 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2865 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2866 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2867 if (rsurfacepass == RSURFPASS_BACKGROUND)
2869 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2870 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2871 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2875 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2877 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2878 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2879 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2880 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2881 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2883 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2884 if (rsurface.rtlight)
2886 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2887 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2894 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2896 // select a permutation of the lighting shader appropriate to this
2897 // combination of texture, entity, light source, and fogging, only use the
2898 // minimum features necessary to avoid wasting rendering time in the
2899 // fragment shader on features that are not being used
2900 unsigned int permutation = 0;
2901 unsigned int mode = 0;
2902 const float *lightcolorbase = rtlight->currentcolor;
2903 float ambientscale = rtlight->ambientscale;
2904 float diffusescale = rtlight->diffusescale;
2905 float specularscale = rtlight->specularscale;
2906 // this is the location of the light in view space
2907 vec3_t viewlightorigin;
2908 // this transforms from view space (camera) to light space (cubemap)
2909 matrix4x4_t viewtolight;
2910 matrix4x4_t lighttoview;
2911 float viewtolight16f[16];
2912 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2914 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2915 if (rtlight->currentcubemap != r_texture_whitecube)
2916 permutation |= SHADERPERMUTATION_CUBEFILTER;
2917 if (diffusescale > 0)
2918 permutation |= SHADERPERMUTATION_DIFFUSE;
2919 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2920 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2921 if (r_shadow_usingshadowmap2d)
2923 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2924 if (r_shadow_shadowmapvsdct)
2925 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2927 if (r_shadow_shadowmapsampler)
2928 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2929 if (r_shadow_shadowmappcf > 1)
2930 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2931 else if (r_shadow_shadowmappcf)
2932 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2934 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2935 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2936 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2937 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2938 switch(vid.renderpath)
2940 case RENDERPATH_D3D9:
2942 R_SetupShader_SetPermutationHLSL(mode, permutation);
2943 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2944 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2945 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2946 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2947 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2948 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2949 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2950 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2951 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2952 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2954 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2955 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2956 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2957 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2958 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2959 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2962 case RENDERPATH_D3D10:
2963 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2965 case RENDERPATH_D3D11:
2966 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2968 case RENDERPATH_GL20:
2969 case RENDERPATH_GLES2:
2970 R_SetupShader_SetPermutationGLSL(mode, permutation);
2971 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2972 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2973 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);
2974 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);
2975 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);
2976 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]);
2977 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]);
2978 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));
2979 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]);
2980 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2982 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2983 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2984 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2985 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2986 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2987 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2989 case RENDERPATH_GL11:
2990 case RENDERPATH_GL13:
2991 case RENDERPATH_GLES1:
2993 case RENDERPATH_SOFT:
2994 R_SetupShader_SetPermutationGLSL(mode, permutation);
2995 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2996 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2997 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2998 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2999 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3000 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3001 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]);
3002 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));
3003 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3004 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3006 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3007 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3008 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3009 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3010 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3011 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3016 #define SKINFRAME_HASH 1024
3020 int loadsequence; // incremented each level change
3021 memexpandablearray_t array;
3022 skinframe_t *hash[SKINFRAME_HASH];
3025 r_skinframe_t r_skinframe;
3027 void R_SkinFrame_PrepareForPurge(void)
3029 r_skinframe.loadsequence++;
3030 // wrap it without hitting zero
3031 if (r_skinframe.loadsequence >= 200)
3032 r_skinframe.loadsequence = 1;
3035 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3039 // mark the skinframe as used for the purging code
3040 skinframe->loadsequence = r_skinframe.loadsequence;
3043 void R_SkinFrame_Purge(void)
3047 for (i = 0;i < SKINFRAME_HASH;i++)
3049 for (s = r_skinframe.hash[i];s;s = s->next)
3051 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3053 if (s->merged == s->base)
3055 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3056 R_PurgeTexture(s->stain );s->stain = NULL;
3057 R_PurgeTexture(s->merged);s->merged = NULL;
3058 R_PurgeTexture(s->base );s->base = NULL;
3059 R_PurgeTexture(s->pants );s->pants = NULL;
3060 R_PurgeTexture(s->shirt );s->shirt = NULL;
3061 R_PurgeTexture(s->nmap );s->nmap = NULL;
3062 R_PurgeTexture(s->gloss );s->gloss = NULL;
3063 R_PurgeTexture(s->glow );s->glow = NULL;
3064 R_PurgeTexture(s->fog );s->fog = NULL;
3065 R_PurgeTexture(s->reflect);s->reflect = NULL;
3066 s->loadsequence = 0;
3072 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3074 char basename[MAX_QPATH];
3076 Image_StripImageExtension(name, basename, sizeof(basename));
3078 if( last == NULL ) {
3080 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3081 item = r_skinframe.hash[hashindex];
3086 // linearly search through the hash bucket
3087 for( ; item ; item = item->next ) {
3088 if( !strcmp( item->basename, basename ) ) {
3095 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3099 char basename[MAX_QPATH];
3101 Image_StripImageExtension(name, basename, sizeof(basename));
3103 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3104 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3105 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3109 rtexture_t *dyntexture;
3110 // check whether its a dynamic texture
3111 dyntexture = CL_GetDynTexture( basename );
3112 if (!add && !dyntexture)
3114 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3115 memset(item, 0, sizeof(*item));
3116 strlcpy(item->basename, basename, sizeof(item->basename));
3117 item->base = dyntexture; // either NULL or dyntexture handle
3118 item->textureflags = textureflags;
3119 item->comparewidth = comparewidth;
3120 item->compareheight = compareheight;
3121 item->comparecrc = comparecrc;
3122 item->next = r_skinframe.hash[hashindex];
3123 r_skinframe.hash[hashindex] = item;
3125 else if( item->base == NULL )
3127 rtexture_t *dyntexture;
3128 // check whether its a dynamic texture
3129 // 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]
3130 dyntexture = CL_GetDynTexture( basename );
3131 item->base = dyntexture; // either NULL or dyntexture handle
3134 R_SkinFrame_MarkUsed(item);
3138 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3140 unsigned long long avgcolor[5], wsum; \
3148 for(pix = 0; pix < cnt; ++pix) \
3151 for(comp = 0; comp < 3; ++comp) \
3153 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3156 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3158 for(comp = 0; comp < 3; ++comp) \
3159 avgcolor[comp] += getpixel * w; \
3162 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3163 avgcolor[4] += getpixel; \
3165 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3167 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3168 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3169 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3170 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3173 extern cvar_t gl_picmip;
3174 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3177 unsigned char *pixels;
3178 unsigned char *bumppixels;
3179 unsigned char *basepixels = NULL;
3180 int basepixels_width = 0;
3181 int basepixels_height = 0;
3182 skinframe_t *skinframe;
3183 rtexture_t *ddsbase = NULL;
3184 qboolean ddshasalpha = false;
3185 float ddsavgcolor[4];
3186 char basename[MAX_QPATH];
3187 int miplevel = R_PicmipForFlags(textureflags);
3188 int savemiplevel = miplevel;
3191 if (cls.state == ca_dedicated)
3194 // return an existing skinframe if already loaded
3195 // if loading of the first image fails, don't make a new skinframe as it
3196 // would cause all future lookups of this to be missing
3197 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3198 if (skinframe && skinframe->base)
3201 Image_StripImageExtension(name, basename, sizeof(basename));
3203 // check for DDS texture file first
3204 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3206 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3207 if (basepixels == NULL)
3211 // FIXME handle miplevel
3213 if (developer_loading.integer)
3214 Con_Printf("loading skin \"%s\"\n", name);
3216 // we've got some pixels to store, so really allocate this new texture now
3218 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3219 skinframe->stain = NULL;
3220 skinframe->merged = NULL;
3221 skinframe->base = NULL;
3222 skinframe->pants = NULL;
3223 skinframe->shirt = NULL;
3224 skinframe->nmap = NULL;
3225 skinframe->gloss = NULL;
3226 skinframe->glow = NULL;
3227 skinframe->fog = NULL;
3228 skinframe->reflect = NULL;
3229 skinframe->hasalpha = false;
3233 skinframe->base = ddsbase;
3234 skinframe->hasalpha = ddshasalpha;
3235 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3236 if (r_loadfog && skinframe->hasalpha)
3237 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3238 //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]);
3242 basepixels_width = image_width;
3243 basepixels_height = image_height;
3244 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);
3245 if (textureflags & TEXF_ALPHA)
3247 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3249 if (basepixels[j] < 255)
3251 skinframe->hasalpha = true;
3255 if (r_loadfog && skinframe->hasalpha)
3257 // has transparent pixels
3258 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3259 for (j = 0;j < image_width * image_height * 4;j += 4)
3264 pixels[j+3] = basepixels[j+3];
3266 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);
3270 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3271 //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]);
3272 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3273 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3274 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3275 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3280 mymiplevel = savemiplevel;
3281 if (r_loadnormalmap)
3282 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);
3283 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3285 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3286 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3287 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3288 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3291 // _norm is the name used by tenebrae and has been adopted as standard
3292 if (r_loadnormalmap && skinframe->nmap == NULL)
3294 mymiplevel = savemiplevel;
3295 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
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);
3301 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3303 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3304 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3305 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);
3307 Mem_Free(bumppixels);
3309 else if (r_shadow_bumpscale_basetexture.value > 0)
3311 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3312 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3313 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);
3316 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3317 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3320 // _luma is supported only for tenebrae compatibility
3321 // _glow is the preferred name
3322 mymiplevel = savemiplevel;
3323 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))))
3325 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);
3326 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3327 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3328 Mem_Free(pixels);pixels = NULL;
3331 mymiplevel = savemiplevel;
3332 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3334 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);
3335 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3336 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3341 mymiplevel = savemiplevel;
3342 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3344 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);
3345 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3346 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3351 mymiplevel = savemiplevel;
3352 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3354 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);
3355 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3356 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3361 mymiplevel = savemiplevel;
3362 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3364 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);
3365 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3366 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3372 Mem_Free(basepixels);
3377 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3378 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3381 unsigned char *temp1, *temp2;
3382 skinframe_t *skinframe;
3384 if (cls.state == ca_dedicated)
3387 // if already loaded just return it, otherwise make a new skinframe
3388 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3389 if (skinframe && skinframe->base)
3392 skinframe->stain = NULL;
3393 skinframe->merged = NULL;
3394 skinframe->base = NULL;
3395 skinframe->pants = NULL;
3396 skinframe->shirt = NULL;
3397 skinframe->nmap = NULL;
3398 skinframe->gloss = NULL;
3399 skinframe->glow = NULL;
3400 skinframe->fog = NULL;
3401 skinframe->reflect = NULL;
3402 skinframe->hasalpha = false;
3404 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3408 if (developer_loading.integer)
3409 Con_Printf("loading 32bit skin \"%s\"\n", name);
3411 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3413 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3414 temp2 = temp1 + width * height * 4;
3415 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3416 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);
3419 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3420 if (textureflags & TEXF_ALPHA)
3422 for (i = 3;i < width * height * 4;i += 4)
3424 if (skindata[i] < 255)
3426 skinframe->hasalpha = true;
3430 if (r_loadfog && skinframe->hasalpha)
3432 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3433 memcpy(fogpixels, skindata, width * height * 4);
3434 for (i = 0;i < width * height * 4;i += 4)
3435 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3436 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3437 Mem_Free(fogpixels);
3441 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3442 //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]);
3447 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3451 skinframe_t *skinframe;
3453 if (cls.state == ca_dedicated)
3456 // if already loaded just return it, otherwise make a new skinframe
3457 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3458 if (skinframe && skinframe->base)
3461 skinframe->stain = NULL;
3462 skinframe->merged = NULL;
3463 skinframe->base = NULL;
3464 skinframe->pants = NULL;
3465 skinframe->shirt = NULL;
3466 skinframe->nmap = NULL;
3467 skinframe->gloss = NULL;
3468 skinframe->glow = NULL;
3469 skinframe->fog = NULL;
3470 skinframe->reflect = NULL;
3471 skinframe->hasalpha = false;
3473 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3477 if (developer_loading.integer)
3478 Con_Printf("loading quake skin \"%s\"\n", name);
3480 // 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)
3481 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3482 memcpy(skinframe->qpixels, skindata, width*height);
3483 skinframe->qwidth = width;
3484 skinframe->qheight = height;
3487 for (i = 0;i < width * height;i++)
3488 featuresmask |= palette_featureflags[skindata[i]];
3490 skinframe->hasalpha = false;
3491 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3492 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3493 skinframe->qgeneratemerged = true;
3494 skinframe->qgeneratebase = skinframe->qhascolormapping;
3495 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3497 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3498 //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]);
3503 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3507 unsigned char *skindata;
3509 if (!skinframe->qpixels)
3512 if (!skinframe->qhascolormapping)
3513 colormapped = false;
3517 if (!skinframe->qgeneratebase)
3522 if (!skinframe->qgeneratemerged)
3526 width = skinframe->qwidth;
3527 height = skinframe->qheight;
3528 skindata = skinframe->qpixels;
3530 if (skinframe->qgeneratenmap)
3532 unsigned char *temp1, *temp2;
3533 skinframe->qgeneratenmap = false;
3534 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3535 temp2 = temp1 + width * height * 4;
3536 // use either a custom palette or the quake palette
3537 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3538 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3539 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);
3543 if (skinframe->qgenerateglow)
3545 skinframe->qgenerateglow = false;
3546 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
3551 skinframe->qgeneratebase = false;
3552 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);
3553 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);
3554 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);
3558 skinframe->qgeneratemerged = false;
3559 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);
3562 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3564 Mem_Free(skinframe->qpixels);
3565 skinframe->qpixels = NULL;
3569 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)
3572 skinframe_t *skinframe;
3574 if (cls.state == ca_dedicated)
3577 // if already loaded just return it, otherwise make a new skinframe
3578 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3579 if (skinframe && skinframe->base)
3582 skinframe->stain = NULL;
3583 skinframe->merged = NULL;
3584 skinframe->base = NULL;
3585 skinframe->pants = NULL;
3586 skinframe->shirt = NULL;
3587 skinframe->nmap = NULL;
3588 skinframe->gloss = NULL;
3589 skinframe->glow = NULL;
3590 skinframe->fog = NULL;
3591 skinframe->reflect = NULL;
3592 skinframe->hasalpha = false;
3594 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3598 if (developer_loading.integer)
3599 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3601 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3602 if (textureflags & TEXF_ALPHA)
3604 for (i = 0;i < width * height;i++)
3606 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3608 skinframe->hasalpha = true;
3612 if (r_loadfog && skinframe->hasalpha)
3613 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3616 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3617 //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]);
3622 skinframe_t *R_SkinFrame_LoadMissing(void)
3624 skinframe_t *skinframe;
3626 if (cls.state == ca_dedicated)
3629 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3630 skinframe->stain = NULL;
3631 skinframe->merged = NULL;
3632 skinframe->base = NULL;
3633 skinframe->pants = NULL;
3634 skinframe->shirt = NULL;
3635 skinframe->nmap = NULL;
3636 skinframe->gloss = NULL;
3637 skinframe->glow = NULL;
3638 skinframe->fog = NULL;
3639 skinframe->reflect = NULL;
3640 skinframe->hasalpha = false;
3642 skinframe->avgcolor[0] = rand() / RAND_MAX;
3643 skinframe->avgcolor[1] = rand() / RAND_MAX;
3644 skinframe->avgcolor[2] = rand() / RAND_MAX;
3645 skinframe->avgcolor[3] = 1;
3650 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3651 typedef struct suffixinfo_s
3654 qboolean flipx, flipy, flipdiagonal;
3657 static suffixinfo_t suffix[3][6] =
3660 {"px", false, false, false},
3661 {"nx", false, false, false},
3662 {"py", false, false, false},
3663 {"ny", false, false, false},
3664 {"pz", false, false, false},
3665 {"nz", false, false, false}
3668 {"posx", false, false, false},
3669 {"negx", false, false, false},
3670 {"posy", false, false, false},
3671 {"negy", false, false, false},
3672 {"posz", false, false, false},
3673 {"negz", false, false, false}
3676 {"rt", true, false, true},
3677 {"lf", false, true, true},
3678 {"ft", true, true, false},
3679 {"bk", false, false, false},
3680 {"up", true, false, true},
3681 {"dn", true, false, true}
3685 static int componentorder[4] = {0, 1, 2, 3};
3687 rtexture_t *R_LoadCubemap(const char *basename)
3689 int i, j, cubemapsize;
3690 unsigned char *cubemappixels, *image_buffer;
3691 rtexture_t *cubemaptexture;
3693 // must start 0 so the first loadimagepixels has no requested width/height
3695 cubemappixels = NULL;
3696 cubemaptexture = NULL;
3697 // keep trying different suffix groups (posx, px, rt) until one loads
3698 for (j = 0;j < 3 && !cubemappixels;j++)
3700 // load the 6 images in the suffix group
3701 for (i = 0;i < 6;i++)
3703 // generate an image name based on the base and and suffix
3704 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3706 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3708 // an image loaded, make sure width and height are equal
3709 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3711 // if this is the first image to load successfully, allocate the cubemap memory
3712 if (!cubemappixels && image_width >= 1)
3714 cubemapsize = image_width;
3715 // note this clears to black, so unavailable sides are black
3716 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3718 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3720 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);
3723 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3725 Mem_Free(image_buffer);
3729 // if a cubemap loaded, upload it
3732 if (developer_loading.integer)
3733 Con_Printf("loading cubemap \"%s\"\n", basename);
3735 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);
3736 Mem_Free(cubemappixels);
3740 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3741 if (developer_loading.integer)
3743 Con_Printf("(tried tried images ");
3744 for (j = 0;j < 3;j++)
3745 for (i = 0;i < 6;i++)
3746 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3747 Con_Print(" and was unable to find any of them).\n");
3750 return cubemaptexture;
3753 rtexture_t *R_GetCubemap(const char *basename)
3756 for (i = 0;i < r_texture_numcubemaps;i++)
3757 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3758 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3759 if (i >= MAX_CUBEMAPS)
3760 return r_texture_whitecube;
3761 r_texture_numcubemaps++;
3762 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3763 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3764 return r_texture_cubemaps[i].texture;
3767 void R_FreeCubemaps(void)
3770 for (i = 0;i < r_texture_numcubemaps;i++)
3772 if (developer_loading.integer)
3773 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3774 if (r_texture_cubemaps[i].texture)
3775 R_FreeTexture(r_texture_cubemaps[i].texture);
3777 r_texture_numcubemaps = 0;
3780 void R_Main_FreeViewCache(void)
3782 if (r_refdef.viewcache.entityvisible)
3783 Mem_Free(r_refdef.viewcache.entityvisible);
3784 if (r_refdef.viewcache.world_pvsbits)
3785 Mem_Free(r_refdef.viewcache.world_pvsbits);
3786 if (r_refdef.viewcache.world_leafvisible)
3787 Mem_Free(r_refdef.viewcache.world_leafvisible);
3788 if (r_refdef.viewcache.world_surfacevisible)
3789 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3790 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3793 void R_Main_ResizeViewCache(void)
3795 int numentities = r_refdef.scene.numentities;
3796 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3797 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3798 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3799 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3800 if (r_refdef.viewcache.maxentities < numentities)
3802 r_refdef.viewcache.maxentities = numentities;
3803 if (r_refdef.viewcache.entityvisible)
3804 Mem_Free(r_refdef.viewcache.entityvisible);
3805 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3807 if (r_refdef.viewcache.world_numclusters != numclusters)
3809 r_refdef.viewcache.world_numclusters = numclusters;
3810 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3811 if (r_refdef.viewcache.world_pvsbits)
3812 Mem_Free(r_refdef.viewcache.world_pvsbits);
3813 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3815 if (r_refdef.viewcache.world_numleafs != numleafs)
3817 r_refdef.viewcache.world_numleafs = numleafs;
3818 if (r_refdef.viewcache.world_leafvisible)
3819 Mem_Free(r_refdef.viewcache.world_leafvisible);
3820 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3822 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3824 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3825 if (r_refdef.viewcache.world_surfacevisible)
3826 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3827 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3831 extern rtexture_t *loadingscreentexture;
3832 void gl_main_start(void)
3834 loadingscreentexture = NULL;
3835 r_texture_blanknormalmap = NULL;
3836 r_texture_white = NULL;
3837 r_texture_grey128 = NULL;
3838 r_texture_black = NULL;
3839 r_texture_whitecube = NULL;
3840 r_texture_normalizationcube = NULL;
3841 r_texture_fogattenuation = NULL;
3842 r_texture_fogheighttexture = NULL;
3843 r_texture_gammaramps = NULL;
3844 r_texture_numcubemaps = 0;
3846 r_loaddds = r_texture_dds_load.integer != 0;
3847 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3849 switch(vid.renderpath)
3851 case RENDERPATH_GL20:
3852 case RENDERPATH_D3D9:
3853 case RENDERPATH_D3D10:
3854 case RENDERPATH_D3D11:
3855 case RENDERPATH_SOFT:
3856 case RENDERPATH_GLES2:
3857 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3858 Cvar_SetValueQuick(&gl_combine, 1);
3859 Cvar_SetValueQuick(&r_glsl, 1);
3860 r_loadnormalmap = true;
3864 case RENDERPATH_GL13:
3865 case RENDERPATH_GLES1:
3866 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3867 Cvar_SetValueQuick(&gl_combine, 1);
3868 Cvar_SetValueQuick(&r_glsl, 0);
3869 r_loadnormalmap = false;
3870 r_loadgloss = false;
3873 case RENDERPATH_GL11:
3874 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3875 Cvar_SetValueQuick(&gl_combine, 0);
3876 Cvar_SetValueQuick(&r_glsl, 0);
3877 r_loadnormalmap = false;
3878 r_loadgloss = false;
3884 R_FrameData_Reset();
3888 memset(r_queries, 0, sizeof(r_queries));
3890 r_qwskincache = NULL;
3891 r_qwskincache_size = 0;
3893 // due to caching of texture_t references, the collision cache must be reset
3894 Collision_Cache_Reset(true);
3896 // set up r_skinframe loading system for textures
3897 memset(&r_skinframe, 0, sizeof(r_skinframe));
3898 r_skinframe.loadsequence = 1;
3899 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3901 r_main_texturepool = R_AllocTexturePool();
3902 R_BuildBlankTextures();
3904 if (vid.support.arb_texture_cube_map)
3907 R_BuildNormalizationCube();
3909 r_texture_fogattenuation = NULL;
3910 r_texture_fogheighttexture = NULL;
3911 r_texture_gammaramps = NULL;
3912 //r_texture_fogintensity = NULL;
3913 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3914 memset(&r_waterstate, 0, sizeof(r_waterstate));
3915 r_glsl_permutation = NULL;
3916 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3917 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3918 glslshaderstring = NULL;
3920 r_hlsl_permutation = NULL;
3921 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3922 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3924 hlslshaderstring = NULL;
3925 memset(&r_svbsp, 0, sizeof (r_svbsp));
3927 r_refdef.fogmasktable_density = 0;
3930 void gl_main_shutdown(void)
3933 R_FrameData_Reset();
3935 R_Main_FreeViewCache();
3937 switch(vid.renderpath)
3939 case RENDERPATH_GL11:
3940 case RENDERPATH_GL13:
3941 case RENDERPATH_GL20:
3942 case RENDERPATH_GLES1:
3943 case RENDERPATH_GLES2:
3945 qglDeleteQueriesARB(r_maxqueries, r_queries);
3947 case RENDERPATH_D3D9:
3948 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3950 case RENDERPATH_D3D10:
3951 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3953 case RENDERPATH_D3D11:
3954 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3956 case RENDERPATH_SOFT:
3962 memset(r_queries, 0, sizeof(r_queries));
3964 r_qwskincache = NULL;
3965 r_qwskincache_size = 0;
3967 // clear out the r_skinframe state
3968 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3969 memset(&r_skinframe, 0, sizeof(r_skinframe));
3972 Mem_Free(r_svbsp.nodes);
3973 memset(&r_svbsp, 0, sizeof (r_svbsp));
3974 R_FreeTexturePool(&r_main_texturepool);
3975 loadingscreentexture = NULL;
3976 r_texture_blanknormalmap = NULL;
3977 r_texture_white = NULL;
3978 r_texture_grey128 = NULL;
3979 r_texture_black = NULL;
3980 r_texture_whitecube = NULL;
3981 r_texture_normalizationcube = NULL;
3982 r_texture_fogattenuation = NULL;
3983 r_texture_fogheighttexture = NULL;
3984 r_texture_gammaramps = NULL;
3985 r_texture_numcubemaps = 0;
3986 //r_texture_fogintensity = NULL;
3987 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3988 memset(&r_waterstate, 0, sizeof(r_waterstate));
3991 r_glsl_permutation = NULL;
3992 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3993 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3994 glslshaderstring = NULL;
3996 r_hlsl_permutation = NULL;
3997 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3998 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4000 hlslshaderstring = NULL;
4003 extern void CL_ParseEntityLump(char *entitystring);
4004 void gl_main_newmap(void)
4006 // FIXME: move this code to client
4007 char *entities, entname[MAX_QPATH];
4009 Mem_Free(r_qwskincache);
4010 r_qwskincache = NULL;
4011 r_qwskincache_size = 0;
4014 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4015 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4017 CL_ParseEntityLump(entities);
4021 if (cl.worldmodel->brush.entities)
4022 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4024 R_Main_FreeViewCache();
4026 R_FrameData_Reset();
4029 void GL_Main_Init(void)
4031 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4033 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4034 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4035 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4036 if (gamemode == GAME_NEHAHRA)
4038 Cvar_RegisterVariable (&gl_fogenable);
4039 Cvar_RegisterVariable (&gl_fogdensity);
4040 Cvar_RegisterVariable (&gl_fogred);
4041 Cvar_RegisterVariable (&gl_foggreen);
4042 Cvar_RegisterVariable (&gl_fogblue);
4043 Cvar_RegisterVariable (&gl_fogstart);
4044 Cvar_RegisterVariable (&gl_fogend);
4045 Cvar_RegisterVariable (&gl_skyclip);
4047 Cvar_RegisterVariable(&r_motionblur);
4048 Cvar_RegisterVariable(&r_motionblur_maxblur);
4049 Cvar_RegisterVariable(&r_motionblur_bmin);
4050 Cvar_RegisterVariable(&r_motionblur_vmin);
4051 Cvar_RegisterVariable(&r_motionblur_vmax);
4052 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4053 Cvar_RegisterVariable(&r_motionblur_randomize);
4054 Cvar_RegisterVariable(&r_damageblur);
4055 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4056 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4057 Cvar_RegisterVariable(&r_equalize_entities_by);
4058 Cvar_RegisterVariable(&r_equalize_entities_to);
4059 Cvar_RegisterVariable(&r_depthfirst);
4060 Cvar_RegisterVariable(&r_useinfinitefarclip);
4061 Cvar_RegisterVariable(&r_farclip_base);
4062 Cvar_RegisterVariable(&r_farclip_world);
4063 Cvar_RegisterVariable(&r_nearclip);
4064 Cvar_RegisterVariable(&r_deformvertexes);
4065 Cvar_RegisterVariable(&r_transparent);
4066 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4067 Cvar_RegisterVariable(&r_showoverdraw);
4068 Cvar_RegisterVariable(&r_showbboxes);
4069 Cvar_RegisterVariable(&r_showsurfaces);
4070 Cvar_RegisterVariable(&r_showtris);
4071 Cvar_RegisterVariable(&r_shownormals);
4072 Cvar_RegisterVariable(&r_showlighting);
4073 Cvar_RegisterVariable(&r_showshadowvolumes);
4074 Cvar_RegisterVariable(&r_showcollisionbrushes);
4075 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4076 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4077 Cvar_RegisterVariable(&r_showdisabledepthtest);
4078 Cvar_RegisterVariable(&r_drawportals);
4079 Cvar_RegisterVariable(&r_drawentities);
4080 Cvar_RegisterVariable(&r_draw2d);
4081 Cvar_RegisterVariable(&r_drawworld);
4082 Cvar_RegisterVariable(&r_cullentities_trace);
4083 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4084 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4085 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4086 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4087 Cvar_RegisterVariable(&r_drawviewmodel);
4088 Cvar_RegisterVariable(&r_drawexteriormodel);
4089 Cvar_RegisterVariable(&r_speeds);
4090 Cvar_RegisterVariable(&r_fullbrights);
4091 Cvar_RegisterVariable(&r_wateralpha);
4092 Cvar_RegisterVariable(&r_dynamic);
4093 Cvar_RegisterVariable(&r_fakelight);
4094 Cvar_RegisterVariable(&r_fakelight_intensity);
4095 Cvar_RegisterVariable(&r_fullbright);
4096 Cvar_RegisterVariable(&r_shadows);
4097 Cvar_RegisterVariable(&r_shadows_darken);
4098 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4099 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4100 Cvar_RegisterVariable(&r_shadows_throwdistance);
4101 Cvar_RegisterVariable(&r_shadows_throwdirection);
4102 Cvar_RegisterVariable(&r_shadows_focus);
4103 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4104 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4105 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4106 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4107 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4108 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4109 Cvar_RegisterVariable(&r_fog_exp2);
4110 Cvar_RegisterVariable(&r_fog_clear);
4111 Cvar_RegisterVariable(&r_drawfog);
4112 Cvar_RegisterVariable(&r_transparentdepthmasking);
4113 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4114 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4115 Cvar_RegisterVariable(&r_texture_dds_load);
4116 Cvar_RegisterVariable(&r_texture_dds_save);
4117 Cvar_RegisterVariable(&r_textureunits);
4118 Cvar_RegisterVariable(&gl_combine);
4119 Cvar_RegisterVariable(&r_viewfbo);
4120 Cvar_RegisterVariable(&r_viewscale);
4121 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4122 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4123 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4124 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4125 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4126 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4127 Cvar_RegisterVariable(&r_glsl);
4128 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4129 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4130 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4131 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4132 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4133 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4134 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4135 Cvar_RegisterVariable(&r_glsl_postprocess);
4136 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4137 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4138 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4139 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4140 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4141 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4142 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4143 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4145 Cvar_RegisterVariable(&r_water);
4146 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4147 Cvar_RegisterVariable(&r_water_clippingplanebias);
4148 Cvar_RegisterVariable(&r_water_refractdistort);
4149 Cvar_RegisterVariable(&r_water_reflectdistort);
4150 Cvar_RegisterVariable(&r_water_scissormode);
4151 Cvar_RegisterVariable(&r_lerpsprites);
4152 Cvar_RegisterVariable(&r_lerpmodels);
4153 Cvar_RegisterVariable(&r_lerplightstyles);
4154 Cvar_RegisterVariable(&r_waterscroll);
4155 Cvar_RegisterVariable(&r_bloom);
4156 Cvar_RegisterVariable(&r_bloom_colorscale);
4157 Cvar_RegisterVariable(&r_bloom_brighten);
4158 Cvar_RegisterVariable(&r_bloom_blur);
4159 Cvar_RegisterVariable(&r_bloom_resolution);
4160 Cvar_RegisterVariable(&r_bloom_colorexponent);
4161 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4162 Cvar_RegisterVariable(&r_hdr);
4163 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4164 Cvar_RegisterVariable(&r_hdr_glowintensity);
4165 Cvar_RegisterVariable(&r_hdr_range);
4166 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4167 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4168 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4169 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4170 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4171 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4172 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4173 Cvar_RegisterVariable(&developer_texturelogging);
4174 Cvar_RegisterVariable(&gl_lightmaps);
4175 Cvar_RegisterVariable(&r_test);
4176 Cvar_RegisterVariable(&r_glsl_saturation);
4177 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4178 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4179 Cvar_RegisterVariable(&r_framedatasize);
4180 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4181 Cvar_SetValue("r_fullbrights", 0);
4182 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4184 Cvar_RegisterVariable(&r_track_sprites);
4185 Cvar_RegisterVariable(&r_track_sprites_flags);
4186 Cvar_RegisterVariable(&r_track_sprites_scalew);
4187 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4188 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4189 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4190 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4191 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4194 extern void R_Textures_Init(void);
4195 extern void GL_Draw_Init(void);
4196 extern void GL_Main_Init(void);
4197 extern void R_Shadow_Init(void);
4198 extern void R_Sky_Init(void);
4199 extern void GL_Surf_Init(void);
4200 extern void R_Particles_Init(void);
4201 extern void R_Explosion_Init(void);
4202 extern void gl_backend_init(void);
4203 extern void Sbar_Init(void);
4204 extern void R_LightningBeams_Init(void);
4205 extern void Mod_RenderInit(void);
4206 extern void Font_Init(void);
4208 void Render_Init(void)
4221 R_LightningBeams_Init();
4230 extern char *ENGINE_EXTENSIONS;
4233 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4234 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4235 gl_version = (const char *)qglGetString(GL_VERSION);
4236 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4240 if (!gl_platformextensions)
4241 gl_platformextensions = "";
4243 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4244 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4245 Con_Printf("GL_VERSION: %s\n", gl_version);
4246 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4247 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4249 VID_CheckExtensions();
4251 // LordHavoc: report supported extensions
4252 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4254 // clear to black (loading plaque will be seen over this)
4255 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4258 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4262 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4264 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4267 p = r_refdef.view.frustum + i;
4272 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4276 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4280 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4284 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4288 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4292 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4296 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4300 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4308 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4312 for (i = 0;i < numplanes;i++)
4319 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4323 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4327 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4331 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4335 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4339 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4343 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4347 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4355 //==================================================================================
4357 // LordHavoc: this stores temporary data used within the same frame
4359 typedef struct r_framedata_mem_s
4361 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4362 size_t size; // how much usable space
4363 size_t current; // how much space in use
4364 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4365 size_t wantedsize; // how much space was allocated
4366 unsigned char *data; // start of real data (16byte aligned)
4370 static r_framedata_mem_t *r_framedata_mem;
4372 void R_FrameData_Reset(void)
4374 while (r_framedata_mem)
4376 r_framedata_mem_t *next = r_framedata_mem->purge;
4377 Mem_Free(r_framedata_mem);
4378 r_framedata_mem = next;
4382 void R_FrameData_Resize(void)
4385 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4386 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4387 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4389 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4390 newmem->wantedsize = wantedsize;
4391 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4392 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4393 newmem->current = 0;
4395 newmem->purge = r_framedata_mem;
4396 r_framedata_mem = newmem;
4400 void R_FrameData_NewFrame(void)
4402 R_FrameData_Resize();
4403 if (!r_framedata_mem)
4405 // if we ran out of space on the last frame, free the old memory now
4406 while (r_framedata_mem->purge)
4408 // repeatedly remove the second item in the list, leaving only head
4409 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4410 Mem_Free(r_framedata_mem->purge);
4411 r_framedata_mem->purge = next;
4413 // reset the current mem pointer
4414 r_framedata_mem->current = 0;
4415 r_framedata_mem->mark = 0;
4418 void *R_FrameData_Alloc(size_t size)
4422 // align to 16 byte boundary - the data pointer is already aligned, so we
4423 // only need to ensure the size of every allocation is also aligned
4424 size = (size + 15) & ~15;
4426 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4428 // emergency - we ran out of space, allocate more memory
4429 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4430 R_FrameData_Resize();
4433 data = r_framedata_mem->data + r_framedata_mem->current;
4434 r_framedata_mem->current += size;
4436 // count the usage for stats
4437 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4438 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4440 return (void *)data;
4443 void *R_FrameData_Store(size_t size, void *data)
4445 void *d = R_FrameData_Alloc(size);
4447 memcpy(d, data, size);
4451 void R_FrameData_SetMark(void)
4453 if (!r_framedata_mem)
4455 r_framedata_mem->mark = r_framedata_mem->current;
4458 void R_FrameData_ReturnToMark(void)
4460 if (!r_framedata_mem)
4462 r_framedata_mem->current = r_framedata_mem->mark;
4465 //==================================================================================
4467 // LordHavoc: animcache originally written by Echon, rewritten since then
4470 * Animation cache prevents re-generating mesh data for an animated model
4471 * multiple times in one frame for lighting, shadowing, reflections, etc.
4474 void R_AnimCache_Free(void)
4478 void R_AnimCache_ClearCache(void)
4481 entity_render_t *ent;
4483 for (i = 0;i < r_refdef.scene.numentities;i++)
4485 ent = r_refdef.scene.entities[i];
4486 ent->animcache_vertex3f = NULL;
4487 ent->animcache_normal3f = NULL;
4488 ent->animcache_svector3f = NULL;
4489 ent->animcache_tvector3f = NULL;
4490 ent->animcache_vertexmesh = NULL;
4491 ent->animcache_vertex3fbuffer = NULL;
4492 ent->animcache_vertexmeshbuffer = NULL;
4496 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4500 // check if we need the meshbuffers
4501 if (!vid.useinterleavedarrays)
4504 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4505 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4506 // TODO: upload vertex3f buffer?
4507 if (ent->animcache_vertexmesh)
4509 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4510 for (i = 0;i < numvertices;i++)
4511 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4512 if (ent->animcache_svector3f)
4513 for (i = 0;i < numvertices;i++)
4514 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4515 if (ent->animcache_tvector3f)
4516 for (i = 0;i < numvertices;i++)
4517 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4518 if (ent->animcache_normal3f)
4519 for (i = 0;i < numvertices;i++)
4520 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4521 // TODO: upload vertexmeshbuffer?
4525 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4527 dp_model_t *model = ent->model;
4529 // see if it's already cached this frame
4530 if (ent->animcache_vertex3f)
4532 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4533 if (wantnormals || wanttangents)
4535 if (ent->animcache_normal3f)
4536 wantnormals = false;
4537 if (ent->animcache_svector3f)
4538 wanttangents = false;
4539 if (wantnormals || wanttangents)
4541 numvertices = model->surfmesh.num_vertices;
4543 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4546 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4547 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4549 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4550 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4556 // see if this ent is worth caching
4557 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4559 // get some memory for this entity and generate mesh data
4560 numvertices = model->surfmesh.num_vertices;
4561 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4563 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4566 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4567 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4569 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4570 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4575 void R_AnimCache_CacheVisibleEntities(void)
4578 qboolean wantnormals = true;
4579 qboolean wanttangents = !r_showsurfaces.integer;
4581 switch(vid.renderpath)
4583 case RENDERPATH_GL20:
4584 case RENDERPATH_D3D9:
4585 case RENDERPATH_D3D10:
4586 case RENDERPATH_D3D11:
4587 case RENDERPATH_GLES2:
4589 case RENDERPATH_GL11:
4590 case RENDERPATH_GL13:
4591 case RENDERPATH_GLES1:
4592 wanttangents = false;
4594 case RENDERPATH_SOFT:
4598 if (r_shownormals.integer)
4599 wanttangents = wantnormals = true;
4601 // TODO: thread this
4602 // NOTE: R_PrepareRTLights() also caches entities
4604 for (i = 0;i < r_refdef.scene.numentities;i++)
4605 if (r_refdef.viewcache.entityvisible[i])
4606 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4609 //==================================================================================
4611 static void R_View_UpdateEntityLighting (void)
4614 entity_render_t *ent;
4615 vec3_t tempdiffusenormal, avg;
4616 vec_t f, fa, fd, fdd;
4617 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4619 for (i = 0;i < r_refdef.scene.numentities;i++)
4621 ent = r_refdef.scene.entities[i];
4623 // skip unseen models
4624 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4628 if (ent->model && ent->model->brush.num_leafs)
4630 // TODO: use modellight for r_ambient settings on world?
4631 VectorSet(ent->modellight_ambient, 0, 0, 0);
4632 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4633 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4637 // fetch the lighting from the worldmodel data
4638 VectorClear(ent->modellight_ambient);
4639 VectorClear(ent->modellight_diffuse);
4640 VectorClear(tempdiffusenormal);
4641 if (ent->flags & RENDER_LIGHT)
4644 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4646 // complete lightning for lit sprites
4647 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4648 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4650 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4651 org[2] = org[2] + r_overheadsprites_pushback.value;
4652 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4655 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4657 if(ent->flags & RENDER_EQUALIZE)
4659 // first fix up ambient lighting...
4660 if(r_equalize_entities_minambient.value > 0)
4662 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4665 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4666 if(fa < r_equalize_entities_minambient.value * fd)
4669 // fa'/fd' = minambient
4670 // fa'+0.25*fd' = fa+0.25*fd
4672 // fa' = fd' * minambient
4673 // fd'*(0.25+minambient) = fa+0.25*fd
4675 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4676 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4678 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4679 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
4680 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4681 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4686 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4688 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4689 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4693 // adjust brightness and saturation to target
4694 avg[0] = avg[1] = avg[2] = fa / f;
4695 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4696 avg[0] = avg[1] = avg[2] = fd / f;
4697 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4703 VectorSet(ent->modellight_ambient, 1, 1, 1);
4705 // move the light direction into modelspace coordinates for lighting code
4706 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4707 if(VectorLength2(ent->modellight_lightdir) == 0)
4708 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4709 VectorNormalize(ent->modellight_lightdir);
4713 #define MAX_LINEOFSIGHTTRACES 64
4715 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4718 vec3_t boxmins, boxmaxs;
4721 dp_model_t *model = r_refdef.scene.worldmodel;
4723 if (!model || !model->brush.TraceLineOfSight)
4726 // expand the box a little
4727 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4728 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4729 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4730 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4731 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4732 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4734 // return true if eye is inside enlarged box
4735 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4739 VectorCopy(eye, start);
4740 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4741 if (model->brush.TraceLineOfSight(model, start, end))
4744 // try various random positions
4745 for (i = 0;i < numsamples;i++)
4747 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4748 if (model->brush.TraceLineOfSight(model, start, end))
4756 static void R_View_UpdateEntityVisible (void)
4761 entity_render_t *ent;
4763 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4764 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4765 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4766 : RENDER_EXTERIORMODEL;
4767 if (!r_drawviewmodel.integer)
4768 renderimask |= RENDER_VIEWMODEL;
4769 if (!r_drawexteriormodel.integer)
4770 renderimask |= RENDER_EXTERIORMODEL;
4771 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4773 // worldmodel can check visibility
4774 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4775 for (i = 0;i < r_refdef.scene.numentities;i++)
4777 ent = r_refdef.scene.entities[i];
4778 if (!(ent->flags & renderimask))
4779 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)))
4780 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))
4781 r_refdef.viewcache.entityvisible[i] = true;
4786 // no worldmodel or it can't check visibility
4787 for (i = 0;i < r_refdef.scene.numentities;i++)
4789 ent = r_refdef.scene.entities[i];
4790 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));
4793 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4794 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4796 for (i = 0;i < r_refdef.scene.numentities;i++)
4798 if (!r_refdef.viewcache.entityvisible[i])
4800 ent = r_refdef.scene.entities[i];
4801 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4803 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4805 continue; // temp entities do pvs only
4806 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4807 ent->last_trace_visibility = realtime;
4808 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4809 r_refdef.viewcache.entityvisible[i] = 0;
4815 /// only used if skyrendermasked, and normally returns false
4816 int R_DrawBrushModelsSky (void)
4819 entity_render_t *ent;
4822 for (i = 0;i < r_refdef.scene.numentities;i++)
4824 if (!r_refdef.viewcache.entityvisible[i])
4826 ent = r_refdef.scene.entities[i];
4827 if (!ent->model || !ent->model->DrawSky)
4829 ent->model->DrawSky(ent);
4835 static void R_DrawNoModel(entity_render_t *ent);
4836 static void R_DrawModels(void)
4839 entity_render_t *ent;
4841 for (i = 0;i < r_refdef.scene.numentities;i++)
4843 if (!r_refdef.viewcache.entityvisible[i])
4845 ent = r_refdef.scene.entities[i];
4846 r_refdef.stats.entities++;
4848 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4851 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4852 Con_Printf("R_DrawModels\n");
4853 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]);
4854 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);
4855 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);
4858 if (ent->model && ent->model->Draw != NULL)
4859 ent->model->Draw(ent);
4865 static void R_DrawModelsDepth(void)
4868 entity_render_t *ent;
4870 for (i = 0;i < r_refdef.scene.numentities;i++)
4872 if (!r_refdef.viewcache.entityvisible[i])
4874 ent = r_refdef.scene.entities[i];
4875 if (ent->model && ent->model->DrawDepth != NULL)
4876 ent->model->DrawDepth(ent);
4880 static void R_DrawModelsDebug(void)
4883 entity_render_t *ent;
4885 for (i = 0;i < r_refdef.scene.numentities;i++)
4887 if (!r_refdef.viewcache.entityvisible[i])
4889 ent = r_refdef.scene.entities[i];
4890 if (ent->model && ent->model->DrawDebug != NULL)
4891 ent->model->DrawDebug(ent);
4895 static void R_DrawModelsAddWaterPlanes(void)
4898 entity_render_t *ent;
4900 for (i = 0;i < r_refdef.scene.numentities;i++)
4902 if (!r_refdef.viewcache.entityvisible[i])
4904 ent = r_refdef.scene.entities[i];
4905 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4906 ent->model->DrawAddWaterPlanes(ent);
4910 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4912 if (r_hdr_irisadaptation.integer)
4916 vec3_t diffusenormal;
4921 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4922 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4923 brightness = max(0.0000001f, brightness);
4924 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4925 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4926 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4927 current = r_hdr_irisadaptation_value.value;
4929 current = min(current + adjust, goal);
4930 else if (current > goal)
4931 current = max(current - adjust, goal);
4932 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4933 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4935 else if (r_hdr_irisadaptation_value.value != 1.0f)
4936 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4939 static void R_View_SetFrustum(const int *scissor)
4942 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4943 vec3_t forward, left, up, origin, v;
4947 // flipped x coordinates (because x points left here)
4948 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4949 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4951 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4952 switch(vid.renderpath)
4954 case RENDERPATH_D3D9:
4955 case RENDERPATH_D3D10:
4956 case RENDERPATH_D3D11:
4957 // non-flipped y coordinates
4958 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4959 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4961 case RENDERPATH_SOFT:
4962 case RENDERPATH_GL11:
4963 case RENDERPATH_GL13:
4964 case RENDERPATH_GL20:
4965 case RENDERPATH_GLES1:
4966 case RENDERPATH_GLES2:
4967 // non-flipped y coordinates
4968 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4969 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4974 // we can't trust r_refdef.view.forward and friends in reflected scenes
4975 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4978 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4979 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4980 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4981 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4982 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4983 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4984 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4985 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4986 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4987 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4988 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4989 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4993 zNear = r_refdef.nearclip;
4994 nudge = 1.0 - 1.0 / (1<<23);
4995 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4996 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4997 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4998 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4999 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5000 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5001 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5002 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5008 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5009 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5010 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5011 r_refdef.view.frustum[0].dist = m[15] - m[12];
5013 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5014 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5015 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5016 r_refdef.view.frustum[1].dist = m[15] + m[12];
5018 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5019 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5020 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5021 r_refdef.view.frustum[2].dist = m[15] - m[13];
5023 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5024 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5025 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5026 r_refdef.view.frustum[3].dist = m[15] + m[13];
5028 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5029 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5030 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5031 r_refdef.view.frustum[4].dist = m[15] - m[14];
5033 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5034 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5035 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5036 r_refdef.view.frustum[5].dist = m[15] + m[14];
5039 if (r_refdef.view.useperspective)
5041 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5042 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]);
5043 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]);
5044 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]);
5045 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]);
5047 // then the normals from the corners relative to origin
5048 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5049 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5050 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5051 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5053 // in a NORMAL view, forward cross left == up
5054 // in a REFLECTED view, forward cross left == down
5055 // so our cross products above need to be adjusted for a left handed coordinate system
5056 CrossProduct(forward, left, v);
5057 if(DotProduct(v, up) < 0)
5059 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5060 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5061 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5062 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5065 // Leaving those out was a mistake, those were in the old code, and they
5066 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5067 // I couldn't reproduce it after adding those normalizations. --blub
5068 VectorNormalize(r_refdef.view.frustum[0].normal);
5069 VectorNormalize(r_refdef.view.frustum[1].normal);
5070 VectorNormalize(r_refdef.view.frustum[2].normal);
5071 VectorNormalize(r_refdef.view.frustum[3].normal);
5073 // make the corners absolute
5074 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5075 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5076 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5077 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5080 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5082 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5083 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5084 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5085 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5086 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5090 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5091 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5092 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5093 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5094 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5095 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5096 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5097 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5098 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5099 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5101 r_refdef.view.numfrustumplanes = 5;
5103 if (r_refdef.view.useclipplane)
5105 r_refdef.view.numfrustumplanes = 6;
5106 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5109 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5110 PlaneClassify(r_refdef.view.frustum + i);
5112 // LordHavoc: note to all quake engine coders, Quake had a special case
5113 // for 90 degrees which assumed a square view (wrong), so I removed it,
5114 // Quake2 has it disabled as well.
5116 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5117 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5118 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5119 //PlaneClassify(&frustum[0]);
5121 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5122 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5123 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5124 //PlaneClassify(&frustum[1]);
5126 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5127 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5128 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5129 //PlaneClassify(&frustum[2]);
5131 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5132 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5133 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5134 //PlaneClassify(&frustum[3]);
5137 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5138 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5139 //PlaneClassify(&frustum[4]);
5142 void R_View_UpdateWithScissor(const int *myscissor)
5144 R_Main_ResizeViewCache();
5145 R_View_SetFrustum(myscissor);
5146 R_View_WorldVisibility(r_refdef.view.useclipplane);
5147 R_View_UpdateEntityVisible();
5148 R_View_UpdateEntityLighting();
5151 void R_View_Update(void)
5153 R_Main_ResizeViewCache();
5154 R_View_SetFrustum(NULL);
5155 R_View_WorldVisibility(r_refdef.view.useclipplane);
5156 R_View_UpdateEntityVisible();
5157 R_View_UpdateEntityLighting();
5160 float viewscalefpsadjusted = 1.0f;
5162 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5164 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5165 scale = bound(0.03125f, scale, 1.0f);
5166 *outwidth = (int)ceil(width * scale);
5167 *outheight = (int)ceil(height * scale);
5170 void R_Mesh_SetMainRenderTargets(void)
5172 if (r_bloomstate.fbo_framebuffer)
5173 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5175 R_Mesh_ResetRenderTargets();
5178 void R_SetupView(qboolean allowwaterclippingplane)
5180 const float *customclipplane = NULL;
5182 int scaledwidth, scaledheight;
5183 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5185 // LordHavoc: couldn't figure out how to make this approach the
5186 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5187 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5188 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5189 dist = r_refdef.view.clipplane.dist;
5190 plane[0] = r_refdef.view.clipplane.normal[0];
5191 plane[1] = r_refdef.view.clipplane.normal[1];
5192 plane[2] = r_refdef.view.clipplane.normal[2];
5194 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5197 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5198 if (!r_refdef.view.useperspective)
5199 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);
5200 else if (vid.stencil && r_useinfinitefarclip.integer)
5201 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);
5203 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);
5204 R_Mesh_SetMainRenderTargets();
5205 R_SetViewport(&r_refdef.view.viewport);
5206 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5208 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5209 float screenplane[4];
5210 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5211 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5212 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5213 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5214 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5218 void R_EntityMatrix(const matrix4x4_t *matrix)
5220 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5222 gl_modelmatrixchanged = false;
5223 gl_modelmatrix = *matrix;
5224 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5225 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5226 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5227 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5229 switch(vid.renderpath)
5231 case RENDERPATH_D3D9:
5233 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5234 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5237 case RENDERPATH_D3D10:
5238 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5240 case RENDERPATH_D3D11:
5241 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5243 case RENDERPATH_GL11:
5244 case RENDERPATH_GL13:
5245 case RENDERPATH_GLES1:
5246 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5248 case RENDERPATH_SOFT:
5249 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5250 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5252 case RENDERPATH_GL20:
5253 case RENDERPATH_GLES2:
5254 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5255 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5261 void R_ResetViewRendering2D(void)
5263 r_viewport_t viewport;
5266 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5267 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);
5268 R_Mesh_ResetRenderTargets();
5269 R_SetViewport(&viewport);
5270 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5271 GL_Color(1, 1, 1, 1);
5272 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5273 GL_BlendFunc(GL_ONE, GL_ZERO);
5274 GL_ScissorTest(false);
5275 GL_DepthMask(false);
5276 GL_DepthRange(0, 1);
5277 GL_DepthTest(false);
5278 GL_DepthFunc(GL_LEQUAL);
5279 R_EntityMatrix(&identitymatrix);
5280 R_Mesh_ResetTextureState();
5281 GL_PolygonOffset(0, 0);
5282 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5283 switch(vid.renderpath)
5285 case RENDERPATH_GL11:
5286 case RENDERPATH_GL13:
5287 case RENDERPATH_GL20:
5288 case RENDERPATH_GLES1:
5289 case RENDERPATH_GLES2:
5290 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5292 case RENDERPATH_D3D9:
5293 case RENDERPATH_D3D10:
5294 case RENDERPATH_D3D11:
5295 case RENDERPATH_SOFT:
5298 GL_CullFace(GL_NONE);
5301 void R_ResetViewRendering3D(void)
5306 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5307 GL_Color(1, 1, 1, 1);
5308 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5309 GL_BlendFunc(GL_ONE, GL_ZERO);
5310 GL_ScissorTest(true);
5312 GL_DepthRange(0, 1);
5314 GL_DepthFunc(GL_LEQUAL);
5315 R_EntityMatrix(&identitymatrix);
5316 R_Mesh_ResetTextureState();
5317 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5318 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5319 switch(vid.renderpath)
5321 case RENDERPATH_GL11:
5322 case RENDERPATH_GL13:
5323 case RENDERPATH_GL20:
5324 case RENDERPATH_GLES1:
5325 case RENDERPATH_GLES2:
5326 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5328 case RENDERPATH_D3D9:
5329 case RENDERPATH_D3D10:
5330 case RENDERPATH_D3D11:
5331 case RENDERPATH_SOFT:
5334 GL_CullFace(r_refdef.view.cullface_back);
5339 R_RenderView_UpdateViewVectors
5342 static void R_RenderView_UpdateViewVectors(void)
5344 // break apart the view matrix into vectors for various purposes
5345 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5346 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5347 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5348 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5349 // make an inverted copy of the view matrix for tracking sprites
5350 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5353 void R_RenderScene(void);
5354 void R_RenderWaterPlanes(void);
5356 static void R_Water_StartFrame(void)
5359 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5360 r_waterstate_waterplane_t *p;
5362 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5365 switch(vid.renderpath)
5367 case RENDERPATH_GL20:
5368 case RENDERPATH_D3D9:
5369 case RENDERPATH_D3D10:
5370 case RENDERPATH_D3D11:
5371 case RENDERPATH_SOFT:
5372 case RENDERPATH_GLES2:
5374 case RENDERPATH_GL11:
5375 case RENDERPATH_GL13:
5376 case RENDERPATH_GLES1:
5380 // set waterwidth and waterheight to the water resolution that will be
5381 // used (often less than the screen resolution for faster rendering)
5382 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5384 // calculate desired texture sizes
5385 // can't use water if the card does not support the texture size
5386 if (!r_water.integer || r_showsurfaces.integer)
5387 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5388 else if (vid.support.arb_texture_non_power_of_two)
5390 texturewidth = waterwidth;
5391 textureheight = waterheight;
5392 camerawidth = waterwidth;
5393 cameraheight = waterheight;
5397 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5398 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5399 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5400 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5403 // allocate textures as needed
5404 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5406 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5407 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5409 if (p->texture_refraction)
5410 R_FreeTexture(p->texture_refraction);
5411 p->texture_refraction = NULL;
5412 if (p->texture_reflection)
5413 R_FreeTexture(p->texture_reflection);
5414 p->texture_reflection = NULL;
5415 if (p->texture_camera)
5416 R_FreeTexture(p->texture_camera);
5417 p->texture_camera = NULL;
5419 memset(&r_waterstate, 0, sizeof(r_waterstate));
5420 r_waterstate.texturewidth = texturewidth;
5421 r_waterstate.textureheight = textureheight;
5422 r_waterstate.camerawidth = camerawidth;
5423 r_waterstate.cameraheight = cameraheight;
5426 if (r_waterstate.texturewidth)
5428 int scaledwidth, scaledheight;
5430 r_waterstate.enabled = true;
5432 // when doing a reduced render (HDR) we want to use a smaller area
5433 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5434 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5435 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5437 // set up variables that will be used in shader setup
5438 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5439 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5440 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5441 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5444 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5445 r_waterstate.numwaterplanes = 0;
5448 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5450 int triangleindex, planeindex;
5456 r_waterstate_waterplane_t *p;
5457 texture_t *t = R_GetCurrentTexture(surface->texture);
5459 // just use the first triangle with a valid normal for any decisions
5460 VectorClear(normal);
5461 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5463 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5464 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5465 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5466 TriangleNormal(vert[0], vert[1], vert[2], normal);
5467 if (VectorLength2(normal) >= 0.001)
5471 VectorCopy(normal, plane.normal);
5472 VectorNormalize(plane.normal);
5473 plane.dist = DotProduct(vert[0], plane.normal);
5474 PlaneClassify(&plane);
5475 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5477 // skip backfaces (except if nocullface is set)
5478 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5480 VectorNegate(plane.normal, plane.normal);
5482 PlaneClassify(&plane);
5486 // find a matching plane if there is one
5487 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5488 if(p->camera_entity == t->camera_entity)
5489 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5491 if (planeindex >= r_waterstate.maxwaterplanes)
5492 return; // nothing we can do, out of planes
5494 // if this triangle does not fit any known plane rendered this frame, add one
5495 if (planeindex >= r_waterstate.numwaterplanes)
5497 // store the new plane
5498 r_waterstate.numwaterplanes++;
5500 // clear materialflags and pvs
5501 p->materialflags = 0;
5502 p->pvsvalid = false;
5503 p->camera_entity = t->camera_entity;
5504 VectorCopy(surface->mins, p->mins);
5505 VectorCopy(surface->maxs, p->maxs);
5510 p->mins[0] = min(p->mins[0], surface->mins[0]);
5511 p->mins[1] = min(p->mins[1], surface->mins[1]);
5512 p->mins[2] = min(p->mins[2], surface->mins[2]);
5513 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5514 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5515 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5517 // merge this surface's materialflags into the waterplane
5518 p->materialflags |= t->currentmaterialflags;
5519 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5521 // merge this surface's PVS into the waterplane
5522 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5523 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5524 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5526 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5532 static void R_Water_ProcessPlanes(void)
5535 r_refdef_view_t originalview;
5536 r_refdef_view_t myview;
5538 r_waterstate_waterplane_t *p;
5541 originalview = r_refdef.view;
5543 // make sure enough textures are allocated
5544 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5546 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5548 if (!p->texture_refraction)
5549 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);
5550 if (!p->texture_refraction)
5553 else if (p->materialflags & MATERIALFLAG_CAMERA)
5555 if (!p->texture_camera)
5556 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);
5557 if (!p->texture_camera)
5561 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5563 if (!p->texture_reflection)
5564 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);
5565 if (!p->texture_reflection)
5571 r_refdef.view = originalview;
5572 r_refdef.view.showdebug = false;
5573 r_refdef.view.width = r_waterstate.waterwidth;
5574 r_refdef.view.height = r_waterstate.waterheight;
5575 r_refdef.view.useclipplane = true;
5576 myview = r_refdef.view;
5577 r_waterstate.renderingscene = true;
5578 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5580 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5582 r_refdef.view = myview;
5583 if(r_water_scissormode.integer)
5586 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5587 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5590 // render reflected scene and copy into texture
5591 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5592 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5593 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5594 r_refdef.view.clipplane = p->plane;
5596 // reverse the cullface settings for this render
5597 r_refdef.view.cullface_front = GL_FRONT;
5598 r_refdef.view.cullface_back = GL_BACK;
5599 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5601 r_refdef.view.usecustompvs = true;
5603 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5605 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5608 R_ResetViewRendering3D();
5609 R_ClearScreen(r_refdef.fogenabled);
5610 if(r_water_scissormode.integer & 2)
5611 R_View_UpdateWithScissor(myscissor);
5614 if(r_water_scissormode.integer & 1)
5615 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5618 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);
5621 // render the normal view scene and copy into texture
5622 // (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)
5623 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5625 r_refdef.view = myview;
5626 if(r_water_scissormode.integer)
5629 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5630 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5633 r_waterstate.renderingrefraction = true;
5635 r_refdef.view.clipplane = p->plane;
5636 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5637 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5639 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5641 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5642 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5643 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5644 R_RenderView_UpdateViewVectors();
5645 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5647 r_refdef.view.usecustompvs = true;
5648 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);
5652 PlaneClassify(&r_refdef.view.clipplane);
5654 R_ResetViewRendering3D();
5655 R_ClearScreen(r_refdef.fogenabled);
5656 if(r_water_scissormode.integer & 2)
5657 R_View_UpdateWithScissor(myscissor);
5660 if(r_water_scissormode.integer & 1)
5661 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5664 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5665 r_waterstate.renderingrefraction = false;
5667 else if (p->materialflags & MATERIALFLAG_CAMERA)
5669 r_refdef.view = myview;
5671 r_refdef.view.clipplane = p->plane;
5672 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5673 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5675 r_refdef.view.width = r_waterstate.camerawidth;
5676 r_refdef.view.height = r_waterstate.cameraheight;
5677 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5678 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5680 if(p->camera_entity)
5682 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5683 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5686 // note: all of the view is used for displaying... so
5687 // there is no use in scissoring
5689 // reverse the cullface settings for this render
5690 r_refdef.view.cullface_front = GL_FRONT;
5691 r_refdef.view.cullface_back = GL_BACK;
5692 // also reverse the view matrix
5693 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
5694 R_RenderView_UpdateViewVectors();
5695 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5697 r_refdef.view.usecustompvs = true;
5698 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);
5701 // camera needs no clipplane
5702 r_refdef.view.useclipplane = false;
5704 PlaneClassify(&r_refdef.view.clipplane);
5706 R_ResetViewRendering3D();
5707 R_ClearScreen(r_refdef.fogenabled);
5711 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);
5712 r_waterstate.renderingrefraction = false;
5716 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5717 r_waterstate.renderingscene = false;
5718 r_refdef.view = originalview;
5719 R_ResetViewRendering3D();
5720 R_ClearScreen(r_refdef.fogenabled);
5724 r_refdef.view = originalview;
5725 r_waterstate.renderingscene = false;
5726 Cvar_SetValueQuick(&r_water, 0);
5727 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5731 void R_Bloom_StartFrame(void)
5733 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5734 int viewwidth, viewheight;
5737 if (r_viewscale_fpsscaling.integer)
5739 double actualframetime;
5740 double targetframetime;
5742 actualframetime = r_refdef.lastdrawscreentime;
5743 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5744 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5745 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5746 if (r_viewscale_fpsscaling_stepsize.value > 0)
5747 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5748 viewscalefpsadjusted += adjust;
5749 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5752 viewscalefpsadjusted = 1.0f;
5754 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5756 switch(vid.renderpath)
5758 case RENDERPATH_GL20:
5759 case RENDERPATH_D3D9:
5760 case RENDERPATH_D3D10:
5761 case RENDERPATH_D3D11:
5762 case RENDERPATH_SOFT:
5763 case RENDERPATH_GLES2:
5765 case RENDERPATH_GL11:
5766 case RENDERPATH_GL13:
5767 case RENDERPATH_GLES1:
5771 // set bloomwidth and bloomheight to the bloom resolution that will be
5772 // used (often less than the screen resolution for faster rendering)
5773 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5774 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5775 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5776 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5777 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5779 // calculate desired texture sizes
5780 if (vid.support.arb_texture_non_power_of_two)
5782 screentexturewidth = vid.width;
5783 screentextureheight = vid.height;
5784 bloomtexturewidth = r_bloomstate.bloomwidth;
5785 bloomtextureheight = r_bloomstate.bloomheight;
5789 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5790 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5791 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5792 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5795 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))
5797 Cvar_SetValueQuick(&r_hdr, 0);
5798 Cvar_SetValueQuick(&r_bloom, 0);
5799 Cvar_SetValueQuick(&r_motionblur, 0);
5800 Cvar_SetValueQuick(&r_damageblur, 0);
5803 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)
5804 screentexturewidth = screentextureheight = 0;
5805 if (!r_hdr.integer && !r_bloom.integer)
5806 bloomtexturewidth = bloomtextureheight = 0;
5808 textype = TEXTYPE_COLORBUFFER;
5809 switch (vid.renderpath)
5811 case RENDERPATH_GL20:
5812 case RENDERPATH_GLES2:
5813 if (vid.support.ext_framebuffer_object)
5815 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5816 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5819 case RENDERPATH_GL11:
5820 case RENDERPATH_GL13:
5821 case RENDERPATH_GLES1:
5822 case RENDERPATH_D3D9:
5823 case RENDERPATH_D3D10:
5824 case RENDERPATH_D3D11:
5825 case RENDERPATH_SOFT:
5829 // allocate textures as needed
5830 if (r_bloomstate.screentexturewidth != screentexturewidth
5831 || r_bloomstate.screentextureheight != screentextureheight
5832 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5833 || r_bloomstate.bloomtextureheight != bloomtextureheight
5834 || r_bloomstate.texturetype != textype
5835 || r_bloomstate.viewfbo != r_viewfbo.integer)
5837 if (r_bloomstate.texture_bloom)
5838 R_FreeTexture(r_bloomstate.texture_bloom);
5839 r_bloomstate.texture_bloom = NULL;
5840 if (r_bloomstate.texture_screen)
5841 R_FreeTexture(r_bloomstate.texture_screen);
5842 r_bloomstate.texture_screen = NULL;
5843 if (r_bloomstate.fbo_framebuffer)
5844 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5845 r_bloomstate.fbo_framebuffer = 0;
5846 if (r_bloomstate.texture_framebuffercolor)
5847 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5848 r_bloomstate.texture_framebuffercolor = NULL;
5849 if (r_bloomstate.texture_framebufferdepth)
5850 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5851 r_bloomstate.texture_framebufferdepth = NULL;
5852 r_bloomstate.screentexturewidth = screentexturewidth;
5853 r_bloomstate.screentextureheight = screentextureheight;
5854 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5855 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);
5856 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5858 // FIXME: choose depth bits based on a cvar
5859 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5860 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);
5861 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5862 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5863 // render depth into one texture and normalmap into the other
5867 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5868 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5869 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5870 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5871 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5874 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5875 r_bloomstate.bloomtextureheight = bloomtextureheight;
5876 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5877 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);
5878 r_bloomstate.viewfbo = r_viewfbo.integer;
5879 r_bloomstate.texturetype = textype;
5882 // when doing a reduced render (HDR) we want to use a smaller area
5883 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5884 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5885 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5886 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5887 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5889 // set up a texcoord array for the full resolution screen image
5890 // (we have to keep this around to copy back during final render)
5891 r_bloomstate.screentexcoord2f[0] = 0;
5892 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5893 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5894 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5895 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5896 r_bloomstate.screentexcoord2f[5] = 0;
5897 r_bloomstate.screentexcoord2f[6] = 0;
5898 r_bloomstate.screentexcoord2f[7] = 0;
5900 // set up a texcoord array for the reduced resolution bloom image
5901 // (which will be additive blended over the screen image)
5902 r_bloomstate.bloomtexcoord2f[0] = 0;
5903 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5904 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5905 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5906 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5907 r_bloomstate.bloomtexcoord2f[5] = 0;
5908 r_bloomstate.bloomtexcoord2f[6] = 0;
5909 r_bloomstate.bloomtexcoord2f[7] = 0;
5911 switch(vid.renderpath)
5913 case RENDERPATH_GL11:
5914 case RENDERPATH_GL13:
5915 case RENDERPATH_GL20:
5916 case RENDERPATH_SOFT:
5917 case RENDERPATH_GLES1:
5918 case RENDERPATH_GLES2:
5920 case RENDERPATH_D3D9:
5921 case RENDERPATH_D3D10:
5922 case RENDERPATH_D3D11:
5925 for (i = 0;i < 4;i++)
5927 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5928 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5929 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5930 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5936 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5938 r_bloomstate.enabled = true;
5939 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5942 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);
5944 if (r_bloomstate.fbo_framebuffer)
5945 r_refdef.view.clear = true;
5948 void R_Bloom_CopyBloomTexture(float colorscale)
5950 r_refdef.stats.bloom++;
5952 // scale down screen texture to the bloom texture size
5954 R_Mesh_SetMainRenderTargets();
5955 R_SetViewport(&r_bloomstate.viewport);
5956 GL_BlendFunc(GL_ONE, GL_ZERO);
5957 GL_Color(colorscale, colorscale, colorscale, 1);
5958 // 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...
5959 switch(vid.renderpath)
5961 case RENDERPATH_GL11:
5962 case RENDERPATH_GL13:
5963 case RENDERPATH_GL20:
5964 case RENDERPATH_GLES1:
5965 case RENDERPATH_GLES2:
5966 case RENDERPATH_SOFT:
5967 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5969 case RENDERPATH_D3D9:
5970 case RENDERPATH_D3D10:
5971 case RENDERPATH_D3D11:
5972 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5975 // TODO: do boxfilter scale-down in shader?
5976 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5977 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5978 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5980 // we now have a bloom image in the framebuffer
5981 // copy it into the bloom image texture for later processing
5982 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);
5983 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5986 void R_Bloom_CopyHDRTexture(void)
5988 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);
5989 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5992 void R_Bloom_MakeTexture(void)
5995 float xoffset, yoffset, r, brighten;
5997 r_refdef.stats.bloom++;
5999 R_ResetViewRendering2D();
6001 // we have a bloom image in the framebuffer
6003 R_SetViewport(&r_bloomstate.viewport);
6005 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6008 r = bound(0, r_bloom_colorexponent.value / x, 1);
6009 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6011 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6012 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6013 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6014 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6016 // copy the vertically blurred bloom view to a texture
6017 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);
6018 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6021 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6022 brighten = r_bloom_brighten.value;
6023 if (r_bloomstate.hdr)
6024 brighten *= r_hdr_range.value;
6025 brighten = sqrt(brighten);
6027 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6028 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6030 for (dir = 0;dir < 2;dir++)
6032 // blend on at multiple vertical offsets to achieve a vertical blur
6033 // TODO: do offset blends using GLSL
6034 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6035 GL_BlendFunc(GL_ONE, GL_ZERO);
6036 for (x = -range;x <= range;x++)
6038 if (!dir){xoffset = 0;yoffset = x;}
6039 else {xoffset = x;yoffset = 0;}
6040 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6041 yoffset /= (float)r_bloomstate.bloomtextureheight;
6042 // compute a texcoord array with the specified x and y offset
6043 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6044 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6045 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6046 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6047 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6048 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6049 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6050 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6051 // this r value looks like a 'dot' particle, fading sharply to
6052 // black at the edges
6053 // (probably not realistic but looks good enough)
6054 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6055 //r = brighten/(range*2+1);
6056 r = brighten / (range * 2 + 1);
6058 r *= (1 - x*x/(float)(range*range));
6059 GL_Color(r, r, r, 1);
6060 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6061 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6062 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6063 GL_BlendFunc(GL_ONE, GL_ONE);
6066 // copy the vertically blurred bloom view to a texture
6067 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);
6068 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6072 void R_HDR_RenderBloomTexture(void)
6074 int oldwidth, oldheight;
6075 float oldcolorscale;
6076 qboolean oldwaterstate;
6078 oldwaterstate = r_waterstate.enabled;
6079 oldcolorscale = r_refdef.view.colorscale;
6080 oldwidth = r_refdef.view.width;
6081 oldheight = r_refdef.view.height;
6082 r_refdef.view.width = r_bloomstate.bloomwidth;
6083 r_refdef.view.height = r_bloomstate.bloomheight;
6085 if(r_hdr.integer < 2)
6086 r_waterstate.enabled = false;
6088 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6089 // TODO: add exposure compensation features
6090 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6092 r_refdef.view.showdebug = false;
6093 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6095 R_ResetViewRendering3D();
6097 R_ClearScreen(r_refdef.fogenabled);
6098 if (r_timereport_active)
6099 R_TimeReport("HDRclear");
6102 if (r_timereport_active)
6103 R_TimeReport("visibility");
6105 // only do secondary renders with HDR if r_hdr is 2 or higher
6106 r_waterstate.numwaterplanes = 0;
6107 if (r_waterstate.enabled)
6108 R_RenderWaterPlanes();
6110 r_refdef.view.showdebug = true;
6112 r_waterstate.numwaterplanes = 0;
6114 R_ResetViewRendering2D();
6116 R_Bloom_CopyHDRTexture();
6117 R_Bloom_MakeTexture();
6119 // restore the view settings
6120 r_waterstate.enabled = oldwaterstate;
6121 r_refdef.view.width = oldwidth;
6122 r_refdef.view.height = oldheight;
6123 r_refdef.view.colorscale = oldcolorscale;
6125 R_ResetViewRendering3D();
6127 R_ClearScreen(r_refdef.fogenabled);
6128 if (r_timereport_active)
6129 R_TimeReport("viewclear");
6132 static void R_BlendView(void)
6134 unsigned int permutation;
6135 float uservecs[4][4];
6137 switch (vid.renderpath)
6139 case RENDERPATH_GL20:
6140 case RENDERPATH_D3D9:
6141 case RENDERPATH_D3D10:
6142 case RENDERPATH_D3D11:
6143 case RENDERPATH_SOFT:
6144 case RENDERPATH_GLES2:
6146 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6147 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6148 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6149 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6150 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6152 if (r_bloomstate.texture_screen)
6154 // make sure the buffer is available
6155 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6157 R_ResetViewRendering2D();
6158 R_Mesh_SetMainRenderTargets();
6160 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6162 // declare variables
6164 static float avgspeed;
6166 speed = VectorLength(cl.movement_velocity);
6168 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6169 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6171 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6172 speed = bound(0, speed, 1);
6173 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6175 // calculate values into a standard alpha
6176 cl.motionbluralpha = 1 - exp(-
6178 (r_motionblur.value * speed / 80)
6180 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6183 max(0.0001, cl.time - cl.oldtime) // fps independent
6186 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6187 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6189 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6191 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6192 GL_Color(1, 1, 1, cl.motionbluralpha);
6193 switch(vid.renderpath)
6195 case RENDERPATH_GL11:
6196 case RENDERPATH_GL13:
6197 case RENDERPATH_GL20:
6198 case RENDERPATH_GLES1:
6199 case RENDERPATH_GLES2:
6200 case RENDERPATH_SOFT:
6201 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6203 case RENDERPATH_D3D9:
6204 case RENDERPATH_D3D10:
6205 case RENDERPATH_D3D11:
6206 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6209 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6210 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6211 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6215 // copy view into the screen texture
6216 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);
6217 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6219 else if (!r_bloomstate.texture_bloom)
6221 // we may still have to do view tint...
6222 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6224 // apply a color tint to the whole view
6225 R_ResetViewRendering2D();
6226 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6227 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6228 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6229 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6230 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6232 break; // no screen processing, no bloom, skip it
6235 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6237 // render simple bloom effect
6238 // copy the screen and shrink it and darken it for the bloom process
6239 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6240 // make the bloom texture
6241 R_Bloom_MakeTexture();
6244 #if _MSC_VER >= 1400
6245 #define sscanf sscanf_s
6247 memset(uservecs, 0, sizeof(uservecs));
6248 if (r_glsl_postprocess_uservec1_enable.integer)
6249 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6250 if (r_glsl_postprocess_uservec2_enable.integer)
6251 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6252 if (r_glsl_postprocess_uservec3_enable.integer)
6253 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6254 if (r_glsl_postprocess_uservec4_enable.integer)
6255 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6257 R_ResetViewRendering2D();
6258 GL_Color(1, 1, 1, 1);
6259 GL_BlendFunc(GL_ONE, GL_ZERO);
6261 switch(vid.renderpath)
6263 case RENDERPATH_GL20:
6264 case RENDERPATH_GLES2:
6265 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6266 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6267 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6268 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6269 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6270 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]);
6271 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6272 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]);
6273 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]);
6274 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]);
6275 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]);
6276 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6277 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6278 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);
6280 case RENDERPATH_D3D9:
6282 // 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...
6283 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6284 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6285 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6286 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6287 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6288 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6289 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6290 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6291 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6292 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6293 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6294 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6295 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6296 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6299 case RENDERPATH_D3D10:
6300 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6302 case RENDERPATH_D3D11:
6303 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6305 case RENDERPATH_SOFT:
6306 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6307 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6308 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6309 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6310 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6311 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6312 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6313 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6314 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6315 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6316 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6317 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6318 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6319 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6324 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6325 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6327 case RENDERPATH_GL11:
6328 case RENDERPATH_GL13:
6329 case RENDERPATH_GLES1:
6330 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6332 // apply a color tint to the whole view
6333 R_ResetViewRendering2D();
6334 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6335 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6336 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6337 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6338 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6344 matrix4x4_t r_waterscrollmatrix;
6346 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6348 if (r_refdef.fog_density)
6350 r_refdef.fogcolor[0] = r_refdef.fog_red;
6351 r_refdef.fogcolor[1] = r_refdef.fog_green;
6352 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6354 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6355 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6356 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6357 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6361 VectorCopy(r_refdef.fogcolor, fogvec);
6362 // color.rgb *= ContrastBoost * SceneBrightness;
6363 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6364 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6365 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6366 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6371 void R_UpdateVariables(void)
6375 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6377 r_refdef.farclip = r_farclip_base.value;
6378 if (r_refdef.scene.worldmodel)
6379 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6380 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6382 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6383 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6384 r_refdef.polygonfactor = 0;
6385 r_refdef.polygonoffset = 0;
6386 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6387 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6389 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6390 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6391 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6392 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6393 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6394 if (FAKELIGHT_ENABLED)
6396 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6398 if (r_showsurfaces.integer)
6400 r_refdef.scene.rtworld = false;
6401 r_refdef.scene.rtworldshadows = false;
6402 r_refdef.scene.rtdlight = false;
6403 r_refdef.scene.rtdlightshadows = false;
6404 r_refdef.lightmapintensity = 0;
6407 if (gamemode == GAME_NEHAHRA)
6409 if (gl_fogenable.integer)
6411 r_refdef.oldgl_fogenable = true;
6412 r_refdef.fog_density = gl_fogdensity.value;
6413 r_refdef.fog_red = gl_fogred.value;
6414 r_refdef.fog_green = gl_foggreen.value;
6415 r_refdef.fog_blue = gl_fogblue.value;
6416 r_refdef.fog_alpha = 1;
6417 r_refdef.fog_start = 0;
6418 r_refdef.fog_end = gl_skyclip.value;
6419 r_refdef.fog_height = 1<<30;
6420 r_refdef.fog_fadedepth = 128;
6422 else if (r_refdef.oldgl_fogenable)
6424 r_refdef.oldgl_fogenable = false;
6425 r_refdef.fog_density = 0;
6426 r_refdef.fog_red = 0;
6427 r_refdef.fog_green = 0;
6428 r_refdef.fog_blue = 0;
6429 r_refdef.fog_alpha = 0;
6430 r_refdef.fog_start = 0;
6431 r_refdef.fog_end = 0;
6432 r_refdef.fog_height = 1<<30;
6433 r_refdef.fog_fadedepth = 128;
6437 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6438 r_refdef.fog_start = max(0, r_refdef.fog_start);
6439 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6441 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6443 if (r_refdef.fog_density && r_drawfog.integer)
6445 r_refdef.fogenabled = true;
6446 // this is the point where the fog reaches 0.9986 alpha, which we
6447 // consider a good enough cutoff point for the texture
6448 // (0.9986 * 256 == 255.6)
6449 if (r_fog_exp2.integer)
6450 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6452 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6453 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6454 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6455 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6456 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6457 R_BuildFogHeightTexture();
6458 // fog color was already set
6459 // update the fog texture
6460 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)
6461 R_BuildFogTexture();
6462 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6463 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6466 r_refdef.fogenabled = false;
6468 switch(vid.renderpath)
6470 case RENDERPATH_GL20:
6471 case RENDERPATH_D3D9:
6472 case RENDERPATH_D3D10:
6473 case RENDERPATH_D3D11:
6474 case RENDERPATH_SOFT:
6475 case RENDERPATH_GLES2:
6476 if(v_glslgamma.integer && !vid_gammatables_trivial)
6478 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6480 // build GLSL gamma texture
6481 #define RAMPWIDTH 256
6482 unsigned short ramp[RAMPWIDTH * 3];
6483 unsigned char rampbgr[RAMPWIDTH][4];
6486 r_texture_gammaramps_serial = vid_gammatables_serial;
6488 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6489 for(i = 0; i < RAMPWIDTH; ++i)
6491 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6492 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6493 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6496 if (r_texture_gammaramps)
6498 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6502 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6508 // remove GLSL gamma texture
6511 case RENDERPATH_GL11:
6512 case RENDERPATH_GL13:
6513 case RENDERPATH_GLES1:
6518 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6519 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6525 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6526 if( scenetype != r_currentscenetype ) {
6527 // store the old scenetype
6528 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6529 r_currentscenetype = scenetype;
6530 // move in the new scene
6531 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6540 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6542 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6543 if( scenetype == r_currentscenetype ) {
6544 return &r_refdef.scene;
6546 return &r_scenes_store[ scenetype ];
6555 int dpsoftrast_test;
6556 void R_RenderView(void)
6558 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6560 dpsoftrast_test = r_test.integer;
6562 if (r_timereport_active)
6563 R_TimeReport("start");
6564 r_textureframe++; // used only by R_GetCurrentTexture
6565 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6567 if(R_CompileShader_CheckStaticParms())
6570 if (!r_drawentities.integer)
6571 r_refdef.scene.numentities = 0;
6573 R_AnimCache_ClearCache();
6574 R_FrameData_NewFrame();
6576 /* adjust for stereo display */
6577 if(R_Stereo_Active())
6579 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);
6580 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6583 if (r_refdef.view.isoverlay)
6585 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6586 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6587 R_TimeReport("depthclear");
6589 r_refdef.view.showdebug = false;
6591 r_waterstate.enabled = false;
6592 r_waterstate.numwaterplanes = 0;
6596 r_refdef.view.matrix = originalmatrix;
6602 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6604 r_refdef.view.matrix = originalmatrix;
6605 return; //Host_Error ("R_RenderView: NULL worldmodel");
6608 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6610 R_RenderView_UpdateViewVectors();
6612 R_Shadow_UpdateWorldLightSelection();
6614 R_Bloom_StartFrame();
6615 R_Water_StartFrame();
6618 if (r_timereport_active)
6619 R_TimeReport("viewsetup");
6621 R_ResetViewRendering3D();
6623 if (r_refdef.view.clear || r_refdef.fogenabled)
6625 R_ClearScreen(r_refdef.fogenabled);
6626 if (r_timereport_active)
6627 R_TimeReport("viewclear");
6629 r_refdef.view.clear = true;
6631 // this produces a bloom texture to be used in R_BlendView() later
6632 if (r_bloomstate.hdr)
6634 R_HDR_RenderBloomTexture();
6635 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6636 r_textureframe++; // used only by R_GetCurrentTexture
6639 r_refdef.view.showdebug = true;
6642 if (r_timereport_active)
6643 R_TimeReport("visibility");
6645 r_waterstate.numwaterplanes = 0;
6646 if (r_waterstate.enabled)
6647 R_RenderWaterPlanes();
6650 r_waterstate.numwaterplanes = 0;
6653 if (r_timereport_active)
6654 R_TimeReport("blendview");
6656 GL_Scissor(0, 0, vid.width, vid.height);
6657 GL_ScissorTest(false);
6659 r_refdef.view.matrix = originalmatrix;
6664 void R_RenderWaterPlanes(void)
6666 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6668 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6669 if (r_timereport_active)
6670 R_TimeReport("waterworld");
6673 // don't let sound skip if going slow
6674 if (r_refdef.scene.extraupdate)
6677 R_DrawModelsAddWaterPlanes();
6678 if (r_timereport_active)
6679 R_TimeReport("watermodels");
6681 if (r_waterstate.numwaterplanes)
6683 R_Water_ProcessPlanes();
6684 if (r_timereport_active)
6685 R_TimeReport("waterscenes");
6689 extern void R_DrawLightningBeams (void);
6690 extern void VM_CL_AddPolygonsToMeshQueue (void);
6691 extern void R_DrawPortals (void);
6692 extern cvar_t cl_locs_show;
6693 static void R_DrawLocs(void);
6694 static void R_DrawEntityBBoxes(void);
6695 static void R_DrawModelDecals(void);
6696 extern void R_DrawModelShadows(void);
6697 extern void R_DrawModelShadowMaps(void);
6698 extern cvar_t cl_decals_newsystem;
6699 extern qboolean r_shadow_usingdeferredprepass;
6700 void R_RenderScene(void)
6702 qboolean shadowmapping = false;
6704 if (r_timereport_active)
6705 R_TimeReport("beginscene");
6707 r_refdef.stats.renders++;
6711 // don't let sound skip if going slow
6712 if (r_refdef.scene.extraupdate)
6715 R_MeshQueue_BeginScene();
6719 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);
6721 if (r_timereport_active)
6722 R_TimeReport("skystartframe");
6724 if (cl.csqc_vidvars.drawworld)
6726 // don't let sound skip if going slow
6727 if (r_refdef.scene.extraupdate)
6730 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6732 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6733 if (r_timereport_active)
6734 R_TimeReport("worldsky");
6737 if (R_DrawBrushModelsSky() && r_timereport_active)
6738 R_TimeReport("bmodelsky");
6740 if (skyrendermasked && skyrenderlater)
6742 // we have to force off the water clipping plane while rendering sky
6746 if (r_timereport_active)
6747 R_TimeReport("sky");
6751 R_AnimCache_CacheVisibleEntities();
6752 if (r_timereport_active)
6753 R_TimeReport("animation");
6755 R_Shadow_PrepareLights();
6756 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6757 R_Shadow_PrepareModelShadows();
6758 if (r_timereport_active)
6759 R_TimeReport("preparelights");
6761 if (R_Shadow_ShadowMappingEnabled())
6762 shadowmapping = true;
6764 if (r_shadow_usingdeferredprepass)
6765 R_Shadow_DrawPrepass();
6767 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6769 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6770 if (r_timereport_active)
6771 R_TimeReport("worlddepth");
6773 if (r_depthfirst.integer >= 2)
6775 R_DrawModelsDepth();
6776 if (r_timereport_active)
6777 R_TimeReport("modeldepth");
6780 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6782 R_DrawModelShadowMaps();
6783 R_ResetViewRendering3D();
6784 // don't let sound skip if going slow
6785 if (r_refdef.scene.extraupdate)
6789 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6791 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6792 if (r_timereport_active)
6793 R_TimeReport("world");
6796 // don't let sound skip if going slow
6797 if (r_refdef.scene.extraupdate)
6801 if (r_timereport_active)
6802 R_TimeReport("models");
6804 // don't let sound skip if going slow
6805 if (r_refdef.scene.extraupdate)
6808 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6810 R_DrawModelShadows();
6811 R_ResetViewRendering3D();
6812 // don't let sound skip if going slow
6813 if (r_refdef.scene.extraupdate)
6817 if (!r_shadow_usingdeferredprepass)
6819 R_Shadow_DrawLights();
6820 if (r_timereport_active)
6821 R_TimeReport("rtlights");
6824 // don't let sound skip if going slow
6825 if (r_refdef.scene.extraupdate)
6828 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6830 R_DrawModelShadows();
6831 R_ResetViewRendering3D();
6832 // don't let sound skip if going slow
6833 if (r_refdef.scene.extraupdate)
6837 if (cl.csqc_vidvars.drawworld)
6839 if (cl_decals_newsystem.integer)
6841 R_DrawModelDecals();
6842 if (r_timereport_active)
6843 R_TimeReport("modeldecals");
6848 if (r_timereport_active)
6849 R_TimeReport("decals");
6853 if (r_timereport_active)
6854 R_TimeReport("particles");
6857 if (r_timereport_active)
6858 R_TimeReport("explosions");
6860 R_DrawLightningBeams();
6861 if (r_timereport_active)
6862 R_TimeReport("lightning");
6865 VM_CL_AddPolygonsToMeshQueue();
6867 if (r_refdef.view.showdebug)
6869 if (cl_locs_show.integer)
6872 if (r_timereport_active)
6873 R_TimeReport("showlocs");
6876 if (r_drawportals.integer)
6879 if (r_timereport_active)
6880 R_TimeReport("portals");
6883 if (r_showbboxes.value > 0)
6885 R_DrawEntityBBoxes();
6886 if (r_timereport_active)
6887 R_TimeReport("bboxes");
6891 if (r_transparent.integer)
6893 R_MeshQueue_RenderTransparent();
6894 if (r_timereport_active)
6895 R_TimeReport("drawtrans");
6898 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))
6900 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6901 if (r_timereport_active)
6902 R_TimeReport("worlddebug");
6903 R_DrawModelsDebug();
6904 if (r_timereport_active)
6905 R_TimeReport("modeldebug");
6908 if (cl.csqc_vidvars.drawworld)
6910 R_Shadow_DrawCoronas();
6911 if (r_timereport_active)
6912 R_TimeReport("coronas");
6917 GL_DepthTest(false);
6918 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6919 GL_Color(1, 1, 1, 1);
6920 qglBegin(GL_POLYGON);
6921 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6922 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6923 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6924 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6926 qglBegin(GL_POLYGON);
6927 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]);
6928 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]);
6929 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]);
6930 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]);
6932 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6936 // don't let sound skip if going slow
6937 if (r_refdef.scene.extraupdate)
6940 R_ResetViewRendering2D();
6943 static const unsigned short bboxelements[36] =
6953 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6956 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6958 RSurf_ActiveWorldEntity();
6960 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6961 GL_DepthMask(false);
6962 GL_DepthRange(0, 1);
6963 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6964 // R_Mesh_ResetTextureState();
6966 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6967 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6968 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6969 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6970 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6971 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6972 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6973 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6974 R_FillColors(color4f, 8, cr, cg, cb, ca);
6975 if (r_refdef.fogenabled)
6977 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6979 f1 = RSurf_FogVertex(v);
6981 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6982 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6983 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6986 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6987 R_Mesh_ResetTextureState();
6988 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6989 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6992 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6996 prvm_edict_t *edict;
6997 prvm_prog_t *prog_save = prog;
6999 // this function draws bounding boxes of server entities
7003 GL_CullFace(GL_NONE);
7004 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7008 for (i = 0;i < numsurfaces;i++)
7010 edict = PRVM_EDICT_NUM(surfacelist[i]);
7011 switch ((int)edict->fields.server->solid)
7013 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7014 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7015 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7016 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7017 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7018 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7020 color[3] *= r_showbboxes.value;
7021 color[3] = bound(0, color[3], 1);
7022 GL_DepthTest(!r_showdisabledepthtest.integer);
7023 GL_CullFace(r_refdef.view.cullface_front);
7024 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7030 static void R_DrawEntityBBoxes(void)
7033 prvm_edict_t *edict;
7035 prvm_prog_t *prog_save = prog;
7037 // this function draws bounding boxes of server entities
7043 for (i = 0;i < prog->num_edicts;i++)
7045 edict = PRVM_EDICT_NUM(i);
7046 if (edict->priv.server->free)
7048 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7049 if(PRVM_EDICTFIELDEDICT(edict, prog->fieldoffsets.tag_entity) != 0)
7051 if(PRVM_EDICTFIELDEDICT(edict, prog->fieldoffsets.viewmodelforclient) != 0)
7053 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7054 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7060 static const int nomodelelement3i[24] =
7072 static const unsigned short nomodelelement3s[24] =
7084 static const float nomodelvertex3f[6*3] =
7094 static const float nomodelcolor4f[6*4] =
7096 0.0f, 0.0f, 0.5f, 1.0f,
7097 0.0f, 0.0f, 0.5f, 1.0f,
7098 0.0f, 0.5f, 0.0f, 1.0f,
7099 0.0f, 0.5f, 0.0f, 1.0f,
7100 0.5f, 0.0f, 0.0f, 1.0f,
7101 0.5f, 0.0f, 0.0f, 1.0f
7104 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7110 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);
7112 // this is only called once per entity so numsurfaces is always 1, and
7113 // surfacelist is always {0}, so this code does not handle batches
7115 if (rsurface.ent_flags & RENDER_ADDITIVE)
7117 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7118 GL_DepthMask(false);
7120 else if (rsurface.colormod[3] < 1)
7122 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7123 GL_DepthMask(false);
7127 GL_BlendFunc(GL_ONE, GL_ZERO);
7130 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7131 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7132 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7133 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7134 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7135 for (i = 0, c = color4f;i < 6;i++, c += 4)
7137 c[0] *= rsurface.colormod[0];
7138 c[1] *= rsurface.colormod[1];
7139 c[2] *= rsurface.colormod[2];
7140 c[3] *= rsurface.colormod[3];
7142 if (r_refdef.fogenabled)
7144 for (i = 0, c = color4f;i < 6;i++, c += 4)
7146 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7148 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7149 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7150 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7153 // R_Mesh_ResetTextureState();
7154 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7155 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7156 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7159 void R_DrawNoModel(entity_render_t *ent)
7162 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7163 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7164 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7166 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7169 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7171 vec3_t right1, right2, diff, normal;
7173 VectorSubtract (org2, org1, normal);
7175 // calculate 'right' vector for start
7176 VectorSubtract (r_refdef.view.origin, org1, diff);
7177 CrossProduct (normal, diff, right1);
7178 VectorNormalize (right1);
7180 // calculate 'right' vector for end
7181 VectorSubtract (r_refdef.view.origin, org2, diff);
7182 CrossProduct (normal, diff, right2);
7183 VectorNormalize (right2);
7185 vert[ 0] = org1[0] + width * right1[0];
7186 vert[ 1] = org1[1] + width * right1[1];
7187 vert[ 2] = org1[2] + width * right1[2];
7188 vert[ 3] = org1[0] - width * right1[0];
7189 vert[ 4] = org1[1] - width * right1[1];
7190 vert[ 5] = org1[2] - width * right1[2];
7191 vert[ 6] = org2[0] - width * right2[0];
7192 vert[ 7] = org2[1] - width * right2[1];
7193 vert[ 8] = org2[2] - width * right2[2];
7194 vert[ 9] = org2[0] + width * right2[0];
7195 vert[10] = org2[1] + width * right2[1];
7196 vert[11] = org2[2] + width * right2[2];
7199 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)
7201 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7202 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7203 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7204 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7205 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7206 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7207 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7208 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7209 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7210 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7211 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7212 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7215 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7220 VectorSet(v, x, y, z);
7221 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7222 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7224 if (i == mesh->numvertices)
7226 if (mesh->numvertices < mesh->maxvertices)
7228 VectorCopy(v, vertex3f);
7229 mesh->numvertices++;
7231 return mesh->numvertices;
7237 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7241 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7242 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7243 e = mesh->element3i + mesh->numtriangles * 3;
7244 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7246 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7247 if (mesh->numtriangles < mesh->maxtriangles)
7252 mesh->numtriangles++;
7254 element[1] = element[2];
7258 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7262 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7263 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7264 e = mesh->element3i + mesh->numtriangles * 3;
7265 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7267 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7268 if (mesh->numtriangles < mesh->maxtriangles)
7273 mesh->numtriangles++;
7275 element[1] = element[2];
7279 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7280 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7282 int planenum, planenum2;
7285 mplane_t *plane, *plane2;
7287 double temppoints[2][256*3];
7288 // figure out how large a bounding box we need to properly compute this brush
7290 for (w = 0;w < numplanes;w++)
7291 maxdist = max(maxdist, fabs(planes[w].dist));
7292 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7293 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7294 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7298 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7299 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7301 if (planenum2 == planenum)
7303 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);
7306 if (tempnumpoints < 3)
7308 // generate elements forming a triangle fan for this polygon
7309 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7313 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)
7315 texturelayer_t *layer;
7316 layer = t->currentlayers + t->currentnumlayers++;
7318 layer->depthmask = depthmask;
7319 layer->blendfunc1 = blendfunc1;
7320 layer->blendfunc2 = blendfunc2;
7321 layer->texture = texture;
7322 layer->texmatrix = *matrix;
7323 layer->color[0] = r;
7324 layer->color[1] = g;
7325 layer->color[2] = b;
7326 layer->color[3] = a;
7329 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7331 if(parms[0] == 0 && parms[1] == 0)
7333 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7334 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7339 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7342 index = parms[2] + r_refdef.scene.time * parms[3];
7343 index -= floor(index);
7344 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7347 case Q3WAVEFUNC_NONE:
7348 case Q3WAVEFUNC_NOISE:
7349 case Q3WAVEFUNC_COUNT:
7352 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7353 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7354 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7355 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7356 case Q3WAVEFUNC_TRIANGLE:
7358 f = index - floor(index);
7369 f = parms[0] + parms[1] * f;
7370 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7371 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7375 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7380 matrix4x4_t matrix, temp;
7381 switch(tcmod->tcmod)
7385 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7386 matrix = r_waterscrollmatrix;
7388 matrix = identitymatrix;
7390 case Q3TCMOD_ENTITYTRANSLATE:
7391 // this is used in Q3 to allow the gamecode to control texcoord
7392 // scrolling on the entity, which is not supported in darkplaces yet.
7393 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7395 case Q3TCMOD_ROTATE:
7396 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7397 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7398 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7401 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7403 case Q3TCMOD_SCROLL:
7404 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7406 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7407 w = (int) tcmod->parms[0];
7408 h = (int) tcmod->parms[1];
7409 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7411 idx = (int) floor(f * w * h);
7412 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7414 case Q3TCMOD_STRETCH:
7415 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7416 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7418 case Q3TCMOD_TRANSFORM:
7419 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7420 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7421 VectorSet(tcmat + 6, 0 , 0 , 1);
7422 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7423 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7425 case Q3TCMOD_TURBULENT:
7426 // this is handled in the RSurf_PrepareVertices function
7427 matrix = identitymatrix;
7431 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7434 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7436 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7437 char name[MAX_QPATH];
7438 skinframe_t *skinframe;
7439 unsigned char pixels[296*194];
7440 strlcpy(cache->name, skinname, sizeof(cache->name));
7441 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7442 if (developer_loading.integer)
7443 Con_Printf("loading %s\n", name);
7444 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7445 if (!skinframe || !skinframe->base)
7448 fs_offset_t filesize;
7450 f = FS_LoadFile(name, tempmempool, true, &filesize);
7453 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7454 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7458 cache->skinframe = skinframe;
7461 texture_t *R_GetCurrentTexture(texture_t *t)
7464 const entity_render_t *ent = rsurface.entity;
7465 dp_model_t *model = ent->model;
7466 q3shaderinfo_layer_tcmod_t *tcmod;
7468 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7469 return t->currentframe;
7470 t->update_lastrenderframe = r_textureframe;
7471 t->update_lastrenderentity = (void *)ent;
7473 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7474 t->camera_entity = ent->entitynumber;
7476 t->camera_entity = 0;
7478 // switch to an alternate material if this is a q1bsp animated material
7480 texture_t *texture = t;
7481 int s = rsurface.ent_skinnum;
7482 if ((unsigned int)s >= (unsigned int)model->numskins)
7484 if (model->skinscenes)
7486 if (model->skinscenes[s].framecount > 1)
7487 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7489 s = model->skinscenes[s].firstframe;
7492 t = t + s * model->num_surfaces;
7495 // use an alternate animation if the entity's frame is not 0,
7496 // and only if the texture has an alternate animation
7497 if (rsurface.ent_alttextures && t->anim_total[1])
7498 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7500 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7502 texture->currentframe = t;
7505 // update currentskinframe to be a qw skin or animation frame
7506 if (rsurface.ent_qwskin >= 0)
7508 i = rsurface.ent_qwskin;
7509 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7511 r_qwskincache_size = cl.maxclients;
7513 Mem_Free(r_qwskincache);
7514 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7516 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7517 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7518 t->currentskinframe = r_qwskincache[i].skinframe;
7519 if (t->currentskinframe == NULL)
7520 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7522 else if (t->numskinframes >= 2)
7523 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7524 if (t->backgroundnumskinframes >= 2)
7525 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7527 t->currentmaterialflags = t->basematerialflags;
7528 t->currentalpha = rsurface.colormod[3];
7529 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7530 t->currentalpha *= r_wateralpha.value;
7531 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7532 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7533 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7534 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7535 if (!(rsurface.ent_flags & RENDER_LIGHT))
7536 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7537 else if (FAKELIGHT_ENABLED)
7539 // no modellight if using fakelight for the map
7541 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7543 // pick a model lighting mode
7544 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7545 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7547 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7549 if (rsurface.ent_flags & RENDER_ADDITIVE)
7550 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7551 else if (t->currentalpha < 1)
7552 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7553 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7554 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7555 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7556 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7557 if (t->backgroundnumskinframes)
7558 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7559 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7561 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7562 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7565 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7566 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7567 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7569 // there is no tcmod
7570 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7572 t->currenttexmatrix = r_waterscrollmatrix;
7573 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7575 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7577 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7578 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7581 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7582 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7583 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7584 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7586 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7587 if (t->currentskinframe->qpixels)
7588 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7589 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7590 if (!t->basetexture)
7591 t->basetexture = r_texture_notexture;
7592 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7593 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7594 t->nmaptexture = t->currentskinframe->nmap;
7595 if (!t->nmaptexture)
7596 t->nmaptexture = r_texture_blanknormalmap;
7597 t->glosstexture = r_texture_black;
7598 t->glowtexture = t->currentskinframe->glow;
7599 t->fogtexture = t->currentskinframe->fog;
7600 t->reflectmasktexture = t->currentskinframe->reflect;
7601 if (t->backgroundnumskinframes)
7603 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7604 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7605 t->backgroundglosstexture = r_texture_black;
7606 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7607 if (!t->backgroundnmaptexture)
7608 t->backgroundnmaptexture = r_texture_blanknormalmap;
7612 t->backgroundbasetexture = r_texture_white;
7613 t->backgroundnmaptexture = r_texture_blanknormalmap;
7614 t->backgroundglosstexture = r_texture_black;
7615 t->backgroundglowtexture = NULL;
7617 t->specularpower = r_shadow_glossexponent.value;
7618 // TODO: store reference values for these in the texture?
7619 t->specularscale = 0;
7620 if (r_shadow_gloss.integer > 0)
7622 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7624 if (r_shadow_glossintensity.value > 0)
7626 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7627 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7628 t->specularscale = r_shadow_glossintensity.value;
7631 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7633 t->glosstexture = r_texture_white;
7634 t->backgroundglosstexture = r_texture_white;
7635 t->specularscale = r_shadow_gloss2intensity.value;
7636 t->specularpower = r_shadow_gloss2exponent.value;
7639 t->specularscale *= t->specularscalemod;
7640 t->specularpower *= t->specularpowermod;
7642 // lightmaps mode looks bad with dlights using actual texturing, so turn
7643 // off the colormap and glossmap, but leave the normalmap on as it still
7644 // accurately represents the shading involved
7645 if (gl_lightmaps.integer)
7647 t->basetexture = r_texture_grey128;
7648 t->pantstexture = r_texture_black;
7649 t->shirttexture = r_texture_black;
7650 t->nmaptexture = r_texture_blanknormalmap;
7651 t->glosstexture = r_texture_black;
7652 t->glowtexture = NULL;
7653 t->fogtexture = NULL;
7654 t->reflectmasktexture = NULL;
7655 t->backgroundbasetexture = NULL;
7656 t->backgroundnmaptexture = r_texture_blanknormalmap;
7657 t->backgroundglosstexture = r_texture_black;
7658 t->backgroundglowtexture = NULL;
7659 t->specularscale = 0;
7660 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7663 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7664 VectorClear(t->dlightcolor);
7665 t->currentnumlayers = 0;
7666 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7668 int blendfunc1, blendfunc2;
7670 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7672 blendfunc1 = GL_SRC_ALPHA;
7673 blendfunc2 = GL_ONE;
7675 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7677 blendfunc1 = GL_SRC_ALPHA;
7678 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7680 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7682 blendfunc1 = t->customblendfunc[0];
7683 blendfunc2 = t->customblendfunc[1];
7687 blendfunc1 = GL_ONE;
7688 blendfunc2 = GL_ZERO;
7690 // don't colormod evilblend textures
7691 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7692 VectorSet(t->lightmapcolor, 1, 1, 1);
7693 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7694 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7696 // fullbright is not affected by r_refdef.lightmapintensity
7697 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]);
7698 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7699 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]);
7700 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7701 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]);
7705 vec3_t ambientcolor;
7707 // set the color tint used for lights affecting this surface
7708 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7710 // q3bsp has no lightmap updates, so the lightstylevalue that
7711 // would normally be baked into the lightmap must be
7712 // applied to the color
7713 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7714 if (model->type == mod_brushq3)
7715 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7716 colorscale *= r_refdef.lightmapintensity;
7717 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7718 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7719 // basic lit geometry
7720 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]);
7721 // add pants/shirt if needed
7722 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7723 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]);
7724 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7725 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]);
7726 // now add ambient passes if needed
7727 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7729 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]);
7730 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7731 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]);
7732 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7733 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]);
7736 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7737 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]);
7738 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7740 // if this is opaque use alpha blend which will darken the earlier
7743 // if this is an alpha blended material, all the earlier passes
7744 // were darkened by fog already, so we only need to add the fog
7745 // color ontop through the fog mask texture
7747 // if this is an additive blended material, all the earlier passes
7748 // were darkened by fog already, and we should not add fog color
7749 // (because the background was not darkened, there is no fog color
7750 // that was lost behind it).
7751 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]);
7755 return t->currentframe;
7758 rsurfacestate_t rsurface;
7760 void RSurf_ActiveWorldEntity(void)
7762 dp_model_t *model = r_refdef.scene.worldmodel;
7763 //if (rsurface.entity == r_refdef.scene.worldentity)
7765 rsurface.entity = r_refdef.scene.worldentity;
7766 rsurface.skeleton = NULL;
7767 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7768 rsurface.ent_skinnum = 0;
7769 rsurface.ent_qwskin = -1;
7770 rsurface.ent_shadertime = 0;
7771 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7772 rsurface.matrix = identitymatrix;
7773 rsurface.inversematrix = identitymatrix;
7774 rsurface.matrixscale = 1;
7775 rsurface.inversematrixscale = 1;
7776 R_EntityMatrix(&identitymatrix);
7777 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7778 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7779 rsurface.fograngerecip = r_refdef.fograngerecip;
7780 rsurface.fogheightfade = r_refdef.fogheightfade;
7781 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7782 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7783 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7784 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7785 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7786 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7787 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7788 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7789 rsurface.colormod[3] = 1;
7790 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);
7791 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7792 rsurface.frameblend[0].lerp = 1;
7793 rsurface.ent_alttextures = false;
7794 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7795 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7796 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7797 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7798 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7799 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7800 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7801 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7802 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7803 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7804 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7805 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7806 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7807 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7808 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7809 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7810 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7811 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7812 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7813 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7814 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7815 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7816 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7817 rsurface.modelelement3i = model->surfmesh.data_element3i;
7818 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7819 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7820 rsurface.modelelement3s = model->surfmesh.data_element3s;
7821 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7822 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7823 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7824 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7825 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7826 rsurface.modelsurfaces = model->data_surfaces;
7827 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7828 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7829 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7830 rsurface.modelgeneratedvertex = false;
7831 rsurface.batchgeneratedvertex = false;
7832 rsurface.batchfirstvertex = 0;
7833 rsurface.batchnumvertices = 0;
7834 rsurface.batchfirsttriangle = 0;
7835 rsurface.batchnumtriangles = 0;
7836 rsurface.batchvertex3f = NULL;
7837 rsurface.batchvertex3f_vertexbuffer = NULL;
7838 rsurface.batchvertex3f_bufferoffset = 0;
7839 rsurface.batchsvector3f = NULL;
7840 rsurface.batchsvector3f_vertexbuffer = NULL;
7841 rsurface.batchsvector3f_bufferoffset = 0;
7842 rsurface.batchtvector3f = NULL;
7843 rsurface.batchtvector3f_vertexbuffer = NULL;
7844 rsurface.batchtvector3f_bufferoffset = 0;
7845 rsurface.batchnormal3f = NULL;
7846 rsurface.batchnormal3f_vertexbuffer = NULL;
7847 rsurface.batchnormal3f_bufferoffset = 0;
7848 rsurface.batchlightmapcolor4f = NULL;
7849 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7850 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7851 rsurface.batchtexcoordtexture2f = NULL;
7852 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7853 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7854 rsurface.batchtexcoordlightmap2f = NULL;
7855 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7856 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7857 rsurface.batchvertexmesh = NULL;
7858 rsurface.batchvertexmeshbuffer = NULL;
7859 rsurface.batchvertex3fbuffer = NULL;
7860 rsurface.batchelement3i = NULL;
7861 rsurface.batchelement3i_indexbuffer = NULL;
7862 rsurface.batchelement3i_bufferoffset = 0;
7863 rsurface.batchelement3s = NULL;
7864 rsurface.batchelement3s_indexbuffer = NULL;
7865 rsurface.batchelement3s_bufferoffset = 0;
7866 rsurface.passcolor4f = NULL;
7867 rsurface.passcolor4f_vertexbuffer = NULL;
7868 rsurface.passcolor4f_bufferoffset = 0;
7871 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7873 dp_model_t *model = ent->model;
7874 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7876 rsurface.entity = (entity_render_t *)ent;
7877 rsurface.skeleton = ent->skeleton;
7878 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7879 rsurface.ent_skinnum = ent->skinnum;
7880 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;
7881 rsurface.ent_shadertime = ent->shadertime;
7882 rsurface.ent_flags = ent->flags;
7883 rsurface.matrix = ent->matrix;
7884 rsurface.inversematrix = ent->inversematrix;
7885 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7886 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7887 R_EntityMatrix(&rsurface.matrix);
7888 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7889 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7890 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7891 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7892 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7893 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7894 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7895 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7896 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7897 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7898 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7899 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7900 rsurface.colormod[3] = ent->alpha;
7901 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7902 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7903 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7904 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7905 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7906 if (ent->model->brush.submodel && !prepass)
7908 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7909 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7911 if (model->surfmesh.isanimated && model->AnimateVertices)
7913 if (ent->animcache_vertex3f)
7915 rsurface.modelvertex3f = ent->animcache_vertex3f;
7916 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7917 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7918 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7919 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7920 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7921 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7923 else if (wanttangents)
7925 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7926 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7927 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7928 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7929 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7930 rsurface.modelvertexmesh = NULL;
7931 rsurface.modelvertexmeshbuffer = NULL;
7932 rsurface.modelvertex3fbuffer = NULL;
7934 else if (wantnormals)
7936 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7937 rsurface.modelsvector3f = NULL;
7938 rsurface.modeltvector3f = NULL;
7939 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7940 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7941 rsurface.modelvertexmesh = NULL;
7942 rsurface.modelvertexmeshbuffer = NULL;
7943 rsurface.modelvertex3fbuffer = NULL;
7947 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7948 rsurface.modelsvector3f = NULL;
7949 rsurface.modeltvector3f = NULL;
7950 rsurface.modelnormal3f = NULL;
7951 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7952 rsurface.modelvertexmesh = NULL;
7953 rsurface.modelvertexmeshbuffer = NULL;
7954 rsurface.modelvertex3fbuffer = NULL;
7956 rsurface.modelvertex3f_vertexbuffer = 0;
7957 rsurface.modelvertex3f_bufferoffset = 0;
7958 rsurface.modelsvector3f_vertexbuffer = 0;
7959 rsurface.modelsvector3f_bufferoffset = 0;
7960 rsurface.modeltvector3f_vertexbuffer = 0;
7961 rsurface.modeltvector3f_bufferoffset = 0;
7962 rsurface.modelnormal3f_vertexbuffer = 0;
7963 rsurface.modelnormal3f_bufferoffset = 0;
7964 rsurface.modelgeneratedvertex = true;
7968 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7969 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7970 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7971 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7972 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7973 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7974 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7975 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7976 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7977 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7978 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7979 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7980 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7981 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7982 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7983 rsurface.modelgeneratedvertex = false;
7985 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7986 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7987 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7988 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7989 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7990 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7991 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7992 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7993 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7994 rsurface.modelelement3i = model->surfmesh.data_element3i;
7995 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7996 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7997 rsurface.modelelement3s = model->surfmesh.data_element3s;
7998 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7999 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8000 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8001 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8002 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8003 rsurface.modelsurfaces = model->data_surfaces;
8004 rsurface.batchgeneratedvertex = false;
8005 rsurface.batchfirstvertex = 0;
8006 rsurface.batchnumvertices = 0;
8007 rsurface.batchfirsttriangle = 0;
8008 rsurface.batchnumtriangles = 0;
8009 rsurface.batchvertex3f = NULL;
8010 rsurface.batchvertex3f_vertexbuffer = NULL;
8011 rsurface.batchvertex3f_bufferoffset = 0;
8012 rsurface.batchsvector3f = NULL;
8013 rsurface.batchsvector3f_vertexbuffer = NULL;
8014 rsurface.batchsvector3f_bufferoffset = 0;
8015 rsurface.batchtvector3f = NULL;
8016 rsurface.batchtvector3f_vertexbuffer = NULL;
8017 rsurface.batchtvector3f_bufferoffset = 0;
8018 rsurface.batchnormal3f = NULL;
8019 rsurface.batchnormal3f_vertexbuffer = NULL;
8020 rsurface.batchnormal3f_bufferoffset = 0;
8021 rsurface.batchlightmapcolor4f = NULL;
8022 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8023 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8024 rsurface.batchtexcoordtexture2f = NULL;
8025 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8026 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8027 rsurface.batchtexcoordlightmap2f = NULL;
8028 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8029 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8030 rsurface.batchvertexmesh = NULL;
8031 rsurface.batchvertexmeshbuffer = NULL;
8032 rsurface.batchvertex3fbuffer = NULL;
8033 rsurface.batchelement3i = NULL;
8034 rsurface.batchelement3i_indexbuffer = NULL;
8035 rsurface.batchelement3i_bufferoffset = 0;
8036 rsurface.batchelement3s = NULL;
8037 rsurface.batchelement3s_indexbuffer = NULL;
8038 rsurface.batchelement3s_bufferoffset = 0;
8039 rsurface.passcolor4f = NULL;
8040 rsurface.passcolor4f_vertexbuffer = NULL;
8041 rsurface.passcolor4f_bufferoffset = 0;
8044 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)
8046 rsurface.entity = r_refdef.scene.worldentity;
8047 rsurface.skeleton = NULL;
8048 rsurface.ent_skinnum = 0;
8049 rsurface.ent_qwskin = -1;
8050 rsurface.ent_shadertime = shadertime;
8051 rsurface.ent_flags = entflags;
8052 rsurface.modelnumvertices = numvertices;
8053 rsurface.modelnumtriangles = numtriangles;
8054 rsurface.matrix = *matrix;
8055 rsurface.inversematrix = *inversematrix;
8056 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8057 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8058 R_EntityMatrix(&rsurface.matrix);
8059 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8060 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8061 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8062 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8063 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8064 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8065 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8066 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8067 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8068 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8069 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8070 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8071 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);
8072 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8073 rsurface.frameblend[0].lerp = 1;
8074 rsurface.ent_alttextures = false;
8075 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8076 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8079 rsurface.modelvertex3f = (float *)vertex3f;
8080 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8081 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8082 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8084 else if (wantnormals)
8086 rsurface.modelvertex3f = (float *)vertex3f;
8087 rsurface.modelsvector3f = NULL;
8088 rsurface.modeltvector3f = NULL;
8089 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8093 rsurface.modelvertex3f = (float *)vertex3f;
8094 rsurface.modelsvector3f = NULL;
8095 rsurface.modeltvector3f = NULL;
8096 rsurface.modelnormal3f = NULL;
8098 rsurface.modelvertexmesh = NULL;
8099 rsurface.modelvertexmeshbuffer = NULL;
8100 rsurface.modelvertex3fbuffer = NULL;
8101 rsurface.modelvertex3f_vertexbuffer = 0;
8102 rsurface.modelvertex3f_bufferoffset = 0;
8103 rsurface.modelsvector3f_vertexbuffer = 0;
8104 rsurface.modelsvector3f_bufferoffset = 0;
8105 rsurface.modeltvector3f_vertexbuffer = 0;
8106 rsurface.modeltvector3f_bufferoffset = 0;
8107 rsurface.modelnormal3f_vertexbuffer = 0;
8108 rsurface.modelnormal3f_bufferoffset = 0;
8109 rsurface.modelgeneratedvertex = true;
8110 rsurface.modellightmapcolor4f = (float *)color4f;
8111 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8112 rsurface.modellightmapcolor4f_bufferoffset = 0;
8113 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8114 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8115 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8116 rsurface.modeltexcoordlightmap2f = NULL;
8117 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8118 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8119 rsurface.modelelement3i = (int *)element3i;
8120 rsurface.modelelement3i_indexbuffer = NULL;
8121 rsurface.modelelement3i_bufferoffset = 0;
8122 rsurface.modelelement3s = (unsigned short *)element3s;
8123 rsurface.modelelement3s_indexbuffer = NULL;
8124 rsurface.modelelement3s_bufferoffset = 0;
8125 rsurface.modellightmapoffsets = NULL;
8126 rsurface.modelsurfaces = NULL;
8127 rsurface.batchgeneratedvertex = false;
8128 rsurface.batchfirstvertex = 0;
8129 rsurface.batchnumvertices = 0;
8130 rsurface.batchfirsttriangle = 0;
8131 rsurface.batchnumtriangles = 0;
8132 rsurface.batchvertex3f = NULL;
8133 rsurface.batchvertex3f_vertexbuffer = NULL;
8134 rsurface.batchvertex3f_bufferoffset = 0;
8135 rsurface.batchsvector3f = NULL;
8136 rsurface.batchsvector3f_vertexbuffer = NULL;
8137 rsurface.batchsvector3f_bufferoffset = 0;
8138 rsurface.batchtvector3f = NULL;
8139 rsurface.batchtvector3f_vertexbuffer = NULL;
8140 rsurface.batchtvector3f_bufferoffset = 0;
8141 rsurface.batchnormal3f = NULL;
8142 rsurface.batchnormal3f_vertexbuffer = NULL;
8143 rsurface.batchnormal3f_bufferoffset = 0;
8144 rsurface.batchlightmapcolor4f = NULL;
8145 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8146 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8147 rsurface.batchtexcoordtexture2f = NULL;
8148 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8149 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8150 rsurface.batchtexcoordlightmap2f = NULL;
8151 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8152 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8153 rsurface.batchvertexmesh = NULL;
8154 rsurface.batchvertexmeshbuffer = NULL;
8155 rsurface.batchvertex3fbuffer = NULL;
8156 rsurface.batchelement3i = NULL;
8157 rsurface.batchelement3i_indexbuffer = NULL;
8158 rsurface.batchelement3i_bufferoffset = 0;
8159 rsurface.batchelement3s = NULL;
8160 rsurface.batchelement3s_indexbuffer = NULL;
8161 rsurface.batchelement3s_bufferoffset = 0;
8162 rsurface.passcolor4f = NULL;
8163 rsurface.passcolor4f_vertexbuffer = NULL;
8164 rsurface.passcolor4f_bufferoffset = 0;
8166 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8168 if ((wantnormals || wanttangents) && !normal3f)
8170 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8171 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8173 if (wanttangents && !svector3f)
8175 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8176 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8177 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8182 float RSurf_FogPoint(const float *v)
8184 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8185 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8186 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8187 float FogHeightFade = r_refdef.fogheightfade;
8189 unsigned int fogmasktableindex;
8190 if (r_refdef.fogplaneviewabove)
8191 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8193 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8194 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8195 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8198 float RSurf_FogVertex(const float *v)
8200 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8201 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8202 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8203 float FogHeightFade = rsurface.fogheightfade;
8205 unsigned int fogmasktableindex;
8206 if (r_refdef.fogplaneviewabove)
8207 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8209 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8210 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8211 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8214 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8217 for (i = 0;i < numelements;i++)
8218 outelement3i[i] = inelement3i[i] + adjust;
8221 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8222 extern cvar_t gl_vbo;
8223 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8231 int surfacefirsttriangle;
8232 int surfacenumtriangles;
8233 int surfacefirstvertex;
8234 int surfaceendvertex;
8235 int surfacenumvertices;
8236 int batchnumvertices;
8237 int batchnumtriangles;
8241 qboolean dynamicvertex;
8245 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8247 q3shaderinfo_deform_t *deform;
8248 const msurface_t *surface, *firstsurface;
8249 r_vertexmesh_t *vertexmesh;
8250 if (!texturenumsurfaces)
8252 // find vertex range of this surface batch
8254 firstsurface = texturesurfacelist[0];
8255 firsttriangle = firstsurface->num_firsttriangle;
8256 batchnumvertices = 0;
8257 batchnumtriangles = 0;
8258 firstvertex = endvertex = firstsurface->num_firstvertex;
8259 for (i = 0;i < texturenumsurfaces;i++)
8261 surface = texturesurfacelist[i];
8262 if (surface != firstsurface + i)
8264 surfacefirstvertex = surface->num_firstvertex;
8265 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8266 surfacenumvertices = surface->num_vertices;
8267 surfacenumtriangles = surface->num_triangles;
8268 if (firstvertex > surfacefirstvertex)
8269 firstvertex = surfacefirstvertex;
8270 if (endvertex < surfaceendvertex)
8271 endvertex = surfaceendvertex;
8272 batchnumvertices += surfacenumvertices;
8273 batchnumtriangles += surfacenumtriangles;
8276 // we now know the vertex range used, and if there are any gaps in it
8277 rsurface.batchfirstvertex = firstvertex;
8278 rsurface.batchnumvertices = endvertex - firstvertex;
8279 rsurface.batchfirsttriangle = firsttriangle;
8280 rsurface.batchnumtriangles = batchnumtriangles;
8282 // this variable holds flags for which properties have been updated that
8283 // may require regenerating vertexmesh array...
8286 // check if any dynamic vertex processing must occur
8287 dynamicvertex = false;
8289 // if there is a chance of animated vertex colors, it's a dynamic batch
8290 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8292 dynamicvertex = true;
8293 batchneed |= BATCHNEED_NOGAPS;
8294 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8297 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8299 switch (deform->deform)
8302 case Q3DEFORM_PROJECTIONSHADOW:
8303 case Q3DEFORM_TEXT0:
8304 case Q3DEFORM_TEXT1:
8305 case Q3DEFORM_TEXT2:
8306 case Q3DEFORM_TEXT3:
8307 case Q3DEFORM_TEXT4:
8308 case Q3DEFORM_TEXT5:
8309 case Q3DEFORM_TEXT6:
8310 case Q3DEFORM_TEXT7:
8313 case Q3DEFORM_AUTOSPRITE:
8314 dynamicvertex = true;
8315 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8316 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8318 case Q3DEFORM_AUTOSPRITE2:
8319 dynamicvertex = true;
8320 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8321 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8323 case Q3DEFORM_NORMAL:
8324 dynamicvertex = true;
8325 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8326 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8329 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8330 break; // if wavefunc is a nop, ignore this transform
8331 dynamicvertex = true;
8332 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8333 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8335 case Q3DEFORM_BULGE:
8336 dynamicvertex = true;
8337 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8338 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8341 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8342 break; // if wavefunc is a nop, ignore this transform
8343 dynamicvertex = true;
8344 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8345 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8349 switch(rsurface.texture->tcgen.tcgen)
8352 case Q3TCGEN_TEXTURE:
8354 case Q3TCGEN_LIGHTMAP:
8355 dynamicvertex = true;
8356 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8357 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8359 case Q3TCGEN_VECTOR:
8360 dynamicvertex = true;
8361 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8362 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8364 case Q3TCGEN_ENVIRONMENT:
8365 dynamicvertex = true;
8366 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8367 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8370 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8372 dynamicvertex = true;
8373 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8374 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8377 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8379 dynamicvertex = true;
8380 batchneed |= BATCHNEED_NOGAPS;
8381 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8384 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8386 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8387 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8388 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8389 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8390 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8391 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8392 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8395 // when the model data has no vertex buffer (dynamic mesh), we need to
8397 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8398 batchneed |= BATCHNEED_NOGAPS;
8400 // if needsupdate, we have to do a dynamic vertex batch for sure
8401 if (needsupdate & batchneed)
8402 dynamicvertex = true;
8404 // see if we need to build vertexmesh from arrays
8405 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8406 dynamicvertex = true;
8408 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8409 // also some drivers strongly dislike firstvertex
8410 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8411 dynamicvertex = true;
8413 rsurface.batchvertex3f = rsurface.modelvertex3f;
8414 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8415 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8416 rsurface.batchsvector3f = rsurface.modelsvector3f;
8417 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8418 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8419 rsurface.batchtvector3f = rsurface.modeltvector3f;
8420 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8421 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8422 rsurface.batchnormal3f = rsurface.modelnormal3f;
8423 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8424 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8425 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8426 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8427 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8428 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8429 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8430 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8431 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8432 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8433 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8434 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8435 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8436 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8437 rsurface.batchelement3i = rsurface.modelelement3i;
8438 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8439 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8440 rsurface.batchelement3s = rsurface.modelelement3s;
8441 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8442 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8444 // if any dynamic vertex processing has to occur in software, we copy the
8445 // entire surface list together before processing to rebase the vertices
8446 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8448 // if any gaps exist and we do not have a static vertex buffer, we have to
8449 // copy the surface list together to avoid wasting upload bandwidth on the
8450 // vertices in the gaps.
8452 // if gaps exist and we have a static vertex buffer, we still have to
8453 // combine the index buffer ranges into one dynamic index buffer.
8455 // in all cases we end up with data that can be drawn in one call.
8459 // static vertex data, just set pointers...
8460 rsurface.batchgeneratedvertex = false;
8461 // if there are gaps, we want to build a combined index buffer,
8462 // otherwise use the original static buffer with an appropriate offset
8465 // build a new triangle elements array for this batch
8466 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8467 rsurface.batchfirsttriangle = 0;
8469 for (i = 0;i < texturenumsurfaces;i++)
8471 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8472 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8473 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8474 numtriangles += surfacenumtriangles;
8476 rsurface.batchelement3i_indexbuffer = NULL;
8477 rsurface.batchelement3i_bufferoffset = 0;
8478 rsurface.batchelement3s = NULL;
8479 rsurface.batchelement3s_indexbuffer = NULL;
8480 rsurface.batchelement3s_bufferoffset = 0;
8481 if (endvertex <= 65536)
8483 // make a 16bit (unsigned short) index array if possible
8484 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8485 for (i = 0;i < numtriangles*3;i++)
8486 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8492 // something needs software processing, do it for real...
8493 // we only directly handle separate array data in this case and then
8494 // generate interleaved data if needed...
8495 rsurface.batchgeneratedvertex = true;
8497 // now copy the vertex data into a combined array and make an index array
8498 // (this is what Quake3 does all the time)
8499 //if (gaps || rsurface.batchfirstvertex)
8501 rsurface.batchvertex3fbuffer = NULL;
8502 rsurface.batchvertexmesh = NULL;
8503 rsurface.batchvertexmeshbuffer = NULL;
8504 rsurface.batchvertex3f = NULL;
8505 rsurface.batchvertex3f_vertexbuffer = NULL;
8506 rsurface.batchvertex3f_bufferoffset = 0;
8507 rsurface.batchsvector3f = NULL;
8508 rsurface.batchsvector3f_vertexbuffer = NULL;
8509 rsurface.batchsvector3f_bufferoffset = 0;
8510 rsurface.batchtvector3f = NULL;
8511 rsurface.batchtvector3f_vertexbuffer = NULL;
8512 rsurface.batchtvector3f_bufferoffset = 0;
8513 rsurface.batchnormal3f = NULL;
8514 rsurface.batchnormal3f_vertexbuffer = NULL;
8515 rsurface.batchnormal3f_bufferoffset = 0;
8516 rsurface.batchlightmapcolor4f = NULL;
8517 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8518 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8519 rsurface.batchtexcoordtexture2f = NULL;
8520 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8521 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8522 rsurface.batchtexcoordlightmap2f = NULL;
8523 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8524 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8525 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8526 rsurface.batchelement3i_indexbuffer = NULL;
8527 rsurface.batchelement3i_bufferoffset = 0;
8528 rsurface.batchelement3s = NULL;
8529 rsurface.batchelement3s_indexbuffer = NULL;
8530 rsurface.batchelement3s_bufferoffset = 0;
8531 // we'll only be setting up certain arrays as needed
8532 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8533 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8534 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8535 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8536 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8537 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8538 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8540 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8541 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8543 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8544 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8545 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8546 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8547 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8548 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8551 for (i = 0;i < texturenumsurfaces;i++)
8553 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8554 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8555 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8556 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8557 // copy only the data requested
8558 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8559 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8560 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8562 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8563 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8564 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8565 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8566 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8568 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8569 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8571 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8572 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8573 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8574 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8575 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8576 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8578 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8579 numvertices += surfacenumvertices;
8580 numtriangles += surfacenumtriangles;
8583 // generate a 16bit index array as well if possible
8584 // (in general, dynamic batches fit)
8585 if (numvertices <= 65536)
8587 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8588 for (i = 0;i < numtriangles*3;i++)
8589 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8592 // since we've copied everything, the batch now starts at 0
8593 rsurface.batchfirstvertex = 0;
8594 rsurface.batchnumvertices = batchnumvertices;
8595 rsurface.batchfirsttriangle = 0;
8596 rsurface.batchnumtriangles = batchnumtriangles;
8599 // q1bsp surfaces rendered in vertex color mode have to have colors
8600 // calculated based on lightstyles
8601 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8603 // generate color arrays for the surfaces in this list
8608 const unsigned char *lm;
8609 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8610 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8611 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8613 for (i = 0;i < texturenumsurfaces;i++)
8615 surface = texturesurfacelist[i];
8616 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8617 surfacenumvertices = surface->num_vertices;
8618 if (surface->lightmapinfo->samples)
8620 for (j = 0;j < surfacenumvertices;j++)
8622 lm = surface->lightmapinfo->samples + offsets[j];
8623 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8624 VectorScale(lm, scale, c);
8625 if (surface->lightmapinfo->styles[1] != 255)
8627 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8629 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8630 VectorMA(c, scale, lm, c);
8631 if (surface->lightmapinfo->styles[2] != 255)
8634 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8635 VectorMA(c, scale, lm, c);
8636 if (surface->lightmapinfo->styles[3] != 255)
8639 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8640 VectorMA(c, scale, lm, c);
8647 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);
8653 for (j = 0;j < surfacenumvertices;j++)
8655 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8662 // if vertices are deformed (sprite flares and things in maps, possibly
8663 // water waves, bulges and other deformations), modify the copied vertices
8665 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8667 switch (deform->deform)
8670 case Q3DEFORM_PROJECTIONSHADOW:
8671 case Q3DEFORM_TEXT0:
8672 case Q3DEFORM_TEXT1:
8673 case Q3DEFORM_TEXT2:
8674 case Q3DEFORM_TEXT3:
8675 case Q3DEFORM_TEXT4:
8676 case Q3DEFORM_TEXT5:
8677 case Q3DEFORM_TEXT6:
8678 case Q3DEFORM_TEXT7:
8681 case Q3DEFORM_AUTOSPRITE:
8682 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8683 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8684 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8685 VectorNormalize(newforward);
8686 VectorNormalize(newright);
8687 VectorNormalize(newup);
8688 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8689 // rsurface.batchvertex3f_vertexbuffer = NULL;
8690 // rsurface.batchvertex3f_bufferoffset = 0;
8691 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8692 // rsurface.batchsvector3f_vertexbuffer = NULL;
8693 // rsurface.batchsvector3f_bufferoffset = 0;
8694 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8695 // rsurface.batchtvector3f_vertexbuffer = NULL;
8696 // rsurface.batchtvector3f_bufferoffset = 0;
8697 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8698 // rsurface.batchnormal3f_vertexbuffer = NULL;
8699 // rsurface.batchnormal3f_bufferoffset = 0;
8700 // a single autosprite surface can contain multiple sprites...
8701 for (j = 0;j < batchnumvertices - 3;j += 4)
8703 VectorClear(center);
8704 for (i = 0;i < 4;i++)
8705 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8706 VectorScale(center, 0.25f, center);
8707 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8708 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8709 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8710 for (i = 0;i < 4;i++)
8712 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8713 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8716 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8717 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8718 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);
8720 case Q3DEFORM_AUTOSPRITE2:
8721 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8722 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8723 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8724 VectorNormalize(newforward);
8725 VectorNormalize(newright);
8726 VectorNormalize(newup);
8727 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8728 // rsurface.batchvertex3f_vertexbuffer = NULL;
8729 // rsurface.batchvertex3f_bufferoffset = 0;
8731 const float *v1, *v2;
8741 memset(shortest, 0, sizeof(shortest));
8742 // a single autosprite surface can contain multiple sprites...
8743 for (j = 0;j < batchnumvertices - 3;j += 4)
8745 VectorClear(center);
8746 for (i = 0;i < 4;i++)
8747 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8748 VectorScale(center, 0.25f, center);
8749 // find the two shortest edges, then use them to define the
8750 // axis vectors for rotating around the central axis
8751 for (i = 0;i < 6;i++)
8753 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8754 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8755 l = VectorDistance2(v1, v2);
8756 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8758 l += (1.0f / 1024.0f);
8759 if (shortest[0].length2 > l || i == 0)
8761 shortest[1] = shortest[0];
8762 shortest[0].length2 = l;
8763 shortest[0].v1 = v1;
8764 shortest[0].v2 = v2;
8766 else if (shortest[1].length2 > l || i == 1)
8768 shortest[1].length2 = l;
8769 shortest[1].v1 = v1;
8770 shortest[1].v2 = v2;
8773 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8774 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8775 // this calculates the right vector from the shortest edge
8776 // and the up vector from the edge midpoints
8777 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8778 VectorNormalize(right);
8779 VectorSubtract(end, start, up);
8780 VectorNormalize(up);
8781 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8782 VectorSubtract(rsurface.localvieworigin, center, forward);
8783 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8784 VectorNegate(forward, forward);
8785 VectorReflect(forward, 0, up, forward);
8786 VectorNormalize(forward);
8787 CrossProduct(up, forward, newright);
8788 VectorNormalize(newright);
8789 // rotate the quad around the up axis vector, this is made
8790 // especially easy by the fact we know the quad is flat,
8791 // so we only have to subtract the center position and
8792 // measure distance along the right vector, and then
8793 // multiply that by the newright vector and add back the
8795 // we also need to subtract the old position to undo the
8796 // displacement from the center, which we do with a
8797 // DotProduct, the subtraction/addition of center is also
8798 // optimized into DotProducts here
8799 l = DotProduct(right, center);
8800 for (i = 0;i < 4;i++)
8802 v1 = rsurface.batchvertex3f + 3*(j+i);
8803 f = DotProduct(right, v1) - l;
8804 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8808 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8810 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8811 // rsurface.batchnormal3f_vertexbuffer = NULL;
8812 // rsurface.batchnormal3f_bufferoffset = 0;
8813 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8815 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8817 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8818 // rsurface.batchsvector3f_vertexbuffer = NULL;
8819 // rsurface.batchsvector3f_bufferoffset = 0;
8820 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8821 // rsurface.batchtvector3f_vertexbuffer = NULL;
8822 // rsurface.batchtvector3f_bufferoffset = 0;
8823 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);
8826 case Q3DEFORM_NORMAL:
8827 // deform the normals to make reflections wavey
8828 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8829 rsurface.batchnormal3f_vertexbuffer = NULL;
8830 rsurface.batchnormal3f_bufferoffset = 0;
8831 for (j = 0;j < batchnumvertices;j++)
8834 float *normal = rsurface.batchnormal3f + 3*j;
8835 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8836 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8837 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]);
8838 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]);
8839 VectorNormalize(normal);
8841 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8843 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8844 // rsurface.batchsvector3f_vertexbuffer = NULL;
8845 // rsurface.batchsvector3f_bufferoffset = 0;
8846 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8847 // rsurface.batchtvector3f_vertexbuffer = NULL;
8848 // rsurface.batchtvector3f_bufferoffset = 0;
8849 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);
8853 // deform vertex array to make wavey water and flags and such
8854 waveparms[0] = deform->waveparms[0];
8855 waveparms[1] = deform->waveparms[1];
8856 waveparms[2] = deform->waveparms[2];
8857 waveparms[3] = deform->waveparms[3];
8858 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8859 break; // if wavefunc is a nop, don't make a dynamic vertex array
8860 // this is how a divisor of vertex influence on deformation
8861 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8862 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8863 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8864 // rsurface.batchvertex3f_vertexbuffer = NULL;
8865 // rsurface.batchvertex3f_bufferoffset = 0;
8866 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8867 // rsurface.batchnormal3f_vertexbuffer = NULL;
8868 // rsurface.batchnormal3f_bufferoffset = 0;
8869 for (j = 0;j < batchnumvertices;j++)
8871 // if the wavefunc depends on time, evaluate it per-vertex
8874 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8875 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8877 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8879 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8880 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8881 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8883 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8884 // rsurface.batchsvector3f_vertexbuffer = NULL;
8885 // rsurface.batchsvector3f_bufferoffset = 0;
8886 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8887 // rsurface.batchtvector3f_vertexbuffer = NULL;
8888 // rsurface.batchtvector3f_bufferoffset = 0;
8889 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);
8892 case Q3DEFORM_BULGE:
8893 // deform vertex array to make the surface have moving bulges
8894 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8895 // rsurface.batchvertex3f_vertexbuffer = NULL;
8896 // rsurface.batchvertex3f_bufferoffset = 0;
8897 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8898 // rsurface.batchnormal3f_vertexbuffer = NULL;
8899 // rsurface.batchnormal3f_bufferoffset = 0;
8900 for (j = 0;j < batchnumvertices;j++)
8902 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8903 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8905 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8906 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8907 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8909 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8910 // rsurface.batchsvector3f_vertexbuffer = NULL;
8911 // rsurface.batchsvector3f_bufferoffset = 0;
8912 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8913 // rsurface.batchtvector3f_vertexbuffer = NULL;
8914 // rsurface.batchtvector3f_bufferoffset = 0;
8915 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);
8919 // deform vertex array
8920 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8921 break; // if wavefunc is a nop, don't make a dynamic vertex array
8922 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8923 VectorScale(deform->parms, scale, waveparms);
8924 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8925 // rsurface.batchvertex3f_vertexbuffer = NULL;
8926 // rsurface.batchvertex3f_bufferoffset = 0;
8927 for (j = 0;j < batchnumvertices;j++)
8928 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8933 // generate texcoords based on the chosen texcoord source
8934 switch(rsurface.texture->tcgen.tcgen)
8937 case Q3TCGEN_TEXTURE:
8939 case Q3TCGEN_LIGHTMAP:
8940 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8941 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8942 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8943 if (rsurface.batchtexcoordlightmap2f)
8944 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8946 case Q3TCGEN_VECTOR:
8947 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8948 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8949 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8950 for (j = 0;j < batchnumvertices;j++)
8952 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8953 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8956 case Q3TCGEN_ENVIRONMENT:
8957 // make environment reflections using a spheremap
8958 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8959 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8960 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8961 for (j = 0;j < batchnumvertices;j++)
8963 // identical to Q3A's method, but executed in worldspace so
8964 // carried models can be shiny too
8966 float viewer[3], d, reflected[3], worldreflected[3];
8968 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8969 // VectorNormalize(viewer);
8971 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8973 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8974 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8975 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8976 // note: this is proportinal to viewer, so we can normalize later
8978 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8979 VectorNormalize(worldreflected);
8981 // note: this sphere map only uses world x and z!
8982 // so positive and negative y will LOOK THE SAME.
8983 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8984 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8988 // the only tcmod that needs software vertex processing is turbulent, so
8989 // check for it here and apply the changes if needed
8990 // and we only support that as the first one
8991 // (handling a mixture of turbulent and other tcmods would be problematic
8992 // without punting it entirely to a software path)
8993 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8995 amplitude = rsurface.texture->tcmods[0].parms[1];
8996 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8997 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8998 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8999 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9000 for (j = 0;j < batchnumvertices;j++)
9002 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);
9003 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9007 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9009 // convert the modified arrays to vertex structs
9010 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9011 // rsurface.batchvertexmeshbuffer = NULL;
9012 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9013 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9014 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9015 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9016 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9017 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9018 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9020 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9022 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9023 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9026 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9027 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9028 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9029 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9030 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9031 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9032 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9033 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9034 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9038 void RSurf_DrawBatch(void)
9040 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9041 // through the pipeline, killing it earlier in the pipeline would have
9042 // per-surface overhead rather than per-batch overhead, so it's best to
9043 // reject it here, before it hits glDraw.
9044 if (rsurface.batchnumtriangles == 0)
9047 // batch debugging code
9048 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9054 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9055 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9058 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9060 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9062 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9063 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);
9070 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);
9073 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9075 // pick the closest matching water plane
9076 int planeindex, vertexindex, bestplaneindex = -1;
9080 r_waterstate_waterplane_t *p;
9081 qboolean prepared = false;
9083 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9085 if(p->camera_entity != rsurface.texture->camera_entity)
9090 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9092 if(rsurface.batchnumvertices == 0)
9095 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9097 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9098 d += fabs(PlaneDiff(vert, &p->plane));
9100 if (bestd > d || bestplaneindex < 0)
9103 bestplaneindex = planeindex;
9106 return bestplaneindex;
9107 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9108 // this situation though, as it might be better to render single larger
9109 // batches with useless stuff (backface culled for example) than to
9110 // render multiple smaller batches
9113 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9116 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9117 rsurface.passcolor4f_vertexbuffer = 0;
9118 rsurface.passcolor4f_bufferoffset = 0;
9119 for (i = 0;i < rsurface.batchnumvertices;i++)
9120 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9123 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9130 if (rsurface.passcolor4f)
9132 // generate color arrays
9133 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9134 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9135 rsurface.passcolor4f_vertexbuffer = 0;
9136 rsurface.passcolor4f_bufferoffset = 0;
9137 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)
9139 f = RSurf_FogVertex(v);
9148 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9149 rsurface.passcolor4f_vertexbuffer = 0;
9150 rsurface.passcolor4f_bufferoffset = 0;
9151 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9153 f = RSurf_FogVertex(v);
9162 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9169 if (!rsurface.passcolor4f)
9171 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9172 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9173 rsurface.passcolor4f_vertexbuffer = 0;
9174 rsurface.passcolor4f_bufferoffset = 0;
9175 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)
9177 f = RSurf_FogVertex(v);
9178 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9179 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9180 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9185 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9190 if (!rsurface.passcolor4f)
9192 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9193 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9194 rsurface.passcolor4f_vertexbuffer = 0;
9195 rsurface.passcolor4f_bufferoffset = 0;
9196 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9205 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9210 if (!rsurface.passcolor4f)
9212 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9213 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9214 rsurface.passcolor4f_vertexbuffer = 0;
9215 rsurface.passcolor4f_bufferoffset = 0;
9216 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9218 c2[0] = c[0] + r_refdef.scene.ambient;
9219 c2[1] = c[1] + r_refdef.scene.ambient;
9220 c2[2] = c[2] + r_refdef.scene.ambient;
9225 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9228 rsurface.passcolor4f = NULL;
9229 rsurface.passcolor4f_vertexbuffer = 0;
9230 rsurface.passcolor4f_bufferoffset = 0;
9231 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9232 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9233 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9234 GL_Color(r, g, b, a);
9235 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9239 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9241 // TODO: optimize applyfog && applycolor case
9242 // just apply fog if necessary, and tint the fog color array if necessary
9243 rsurface.passcolor4f = NULL;
9244 rsurface.passcolor4f_vertexbuffer = 0;
9245 rsurface.passcolor4f_bufferoffset = 0;
9246 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9247 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9248 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9249 GL_Color(r, g, b, a);
9253 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9256 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9257 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9258 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9259 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9260 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9261 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9262 GL_Color(r, g, b, a);
9266 static void RSurf_DrawBatch_GL11_ClampColor(void)
9271 if (!rsurface.passcolor4f)
9273 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9275 c2[0] = bound(0.0f, c1[0], 1.0f);
9276 c2[1] = bound(0.0f, c1[1], 1.0f);
9277 c2[2] = bound(0.0f, c1[2], 1.0f);
9278 c2[3] = bound(0.0f, c1[3], 1.0f);
9282 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9292 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9293 rsurface.passcolor4f_vertexbuffer = 0;
9294 rsurface.passcolor4f_bufferoffset = 0;
9295 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)
9297 f = -DotProduct(r_refdef.view.forward, n);
9299 f = f * 0.85 + 0.15; // work around so stuff won't get black
9300 f *= r_refdef.lightmapintensity;
9301 Vector4Set(c, f, f, f, 1);
9305 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9307 RSurf_DrawBatch_GL11_ApplyFakeLight();
9308 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9309 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9310 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9311 GL_Color(r, g, b, a);
9315 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9323 vec3_t ambientcolor;
9324 vec3_t diffusecolor;
9328 VectorCopy(rsurface.modellight_lightdir, lightdir);
9329 f = 0.5f * r_refdef.lightmapintensity;
9330 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9331 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9332 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9333 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9334 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9335 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9337 if (VectorLength2(diffusecolor) > 0)
9339 // q3-style directional shading
9340 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9341 rsurface.passcolor4f_vertexbuffer = 0;
9342 rsurface.passcolor4f_bufferoffset = 0;
9343 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)
9345 if ((f = DotProduct(n, lightdir)) > 0)
9346 VectorMA(ambientcolor, f, diffusecolor, c);
9348 VectorCopy(ambientcolor, c);
9355 *applycolor = false;
9359 *r = ambientcolor[0];
9360 *g = ambientcolor[1];
9361 *b = ambientcolor[2];
9362 rsurface.passcolor4f = NULL;
9363 rsurface.passcolor4f_vertexbuffer = 0;
9364 rsurface.passcolor4f_bufferoffset = 0;
9368 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9370 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9371 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9372 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9373 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9374 GL_Color(r, g, b, a);
9378 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9386 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9387 rsurface.passcolor4f_vertexbuffer = 0;
9388 rsurface.passcolor4f_bufferoffset = 0;
9390 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9392 f = 1 - RSurf_FogVertex(v);
9400 void RSurf_SetupDepthAndCulling(void)
9402 // submodels are biased to avoid z-fighting with world surfaces that they
9403 // may be exactly overlapping (avoids z-fighting artifacts on certain
9404 // doors and things in Quake maps)
9405 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9406 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9407 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9408 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9411 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9413 // transparent sky would be ridiculous
9414 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9416 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9417 skyrenderlater = true;
9418 RSurf_SetupDepthAndCulling();
9420 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9421 // skymasking on them, and Quake3 never did sky masking (unlike
9422 // software Quake and software Quake2), so disable the sky masking
9423 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9424 // and skymasking also looks very bad when noclipping outside the
9425 // level, so don't use it then either.
9426 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9428 R_Mesh_ResetTextureState();
9429 if (skyrendermasked)
9431 R_SetupShader_DepthOrShadow();
9432 // depth-only (masking)
9433 GL_ColorMask(0,0,0,0);
9434 // just to make sure that braindead drivers don't draw
9435 // anything despite that colormask...
9436 GL_BlendFunc(GL_ZERO, GL_ONE);
9437 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9438 if (rsurface.batchvertex3fbuffer)
9439 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9441 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9445 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9447 GL_BlendFunc(GL_ONE, GL_ZERO);
9448 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9449 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9450 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9453 if (skyrendermasked)
9454 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9456 R_Mesh_ResetTextureState();
9457 GL_Color(1, 1, 1, 1);
9460 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9461 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9462 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9464 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9468 // render screenspace normalmap to texture
9470 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9475 // bind lightmap texture
9477 // water/refraction/reflection/camera surfaces have to be handled specially
9478 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9480 int start, end, startplaneindex;
9481 for (start = 0;start < texturenumsurfaces;start = end)
9483 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9484 if(startplaneindex < 0)
9486 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9487 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9491 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9493 // now that we have a batch using the same planeindex, render it
9494 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9496 // render water or distortion background
9498 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));
9500 // blend surface on top
9501 GL_DepthMask(false);
9502 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9505 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9507 // render surface with reflection texture as input
9508 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9509 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));
9516 // render surface batch normally
9517 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9518 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9522 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9524 // OpenGL 1.3 path - anything not completely ancient
9525 qboolean applycolor;
9528 const texturelayer_t *layer;
9529 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);
9530 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9532 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9535 int layertexrgbscale;
9536 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9538 if (layerindex == 0)
9542 GL_AlphaTest(false);
9543 GL_DepthFunc(GL_EQUAL);
9546 GL_DepthMask(layer->depthmask && writedepth);
9547 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9548 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9550 layertexrgbscale = 4;
9551 VectorScale(layer->color, 0.25f, layercolor);
9553 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9555 layertexrgbscale = 2;
9556 VectorScale(layer->color, 0.5f, layercolor);
9560 layertexrgbscale = 1;
9561 VectorScale(layer->color, 1.0f, layercolor);
9563 layercolor[3] = layer->color[3];
9564 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9565 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9566 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9567 switch (layer->type)
9569 case TEXTURELAYERTYPE_LITTEXTURE:
9570 // single-pass lightmapped texture with 2x rgbscale
9571 R_Mesh_TexBind(0, r_texture_white);
9572 R_Mesh_TexMatrix(0, NULL);
9573 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9574 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9575 R_Mesh_TexBind(1, layer->texture);
9576 R_Mesh_TexMatrix(1, &layer->texmatrix);
9577 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9578 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9579 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9580 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9581 else if (FAKELIGHT_ENABLED)
9582 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9583 else if (rsurface.uselightmaptexture)
9584 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9586 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9588 case TEXTURELAYERTYPE_TEXTURE:
9589 // singletexture unlit texture with transparency support
9590 R_Mesh_TexBind(0, layer->texture);
9591 R_Mesh_TexMatrix(0, &layer->texmatrix);
9592 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9593 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9594 R_Mesh_TexBind(1, 0);
9595 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9596 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9598 case TEXTURELAYERTYPE_FOG:
9599 // singletexture fogging
9602 R_Mesh_TexBind(0, layer->texture);
9603 R_Mesh_TexMatrix(0, &layer->texmatrix);
9604 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9605 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9609 R_Mesh_TexBind(0, 0);
9610 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9612 R_Mesh_TexBind(1, 0);
9613 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9614 // generate a color array for the fog pass
9615 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9616 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9620 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9623 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9625 GL_DepthFunc(GL_LEQUAL);
9626 GL_AlphaTest(false);
9630 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9632 // OpenGL 1.1 - crusty old voodoo path
9635 const texturelayer_t *layer;
9636 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);
9637 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9639 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9641 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9643 if (layerindex == 0)
9647 GL_AlphaTest(false);
9648 GL_DepthFunc(GL_EQUAL);
9651 GL_DepthMask(layer->depthmask && writedepth);
9652 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9653 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9654 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9655 switch (layer->type)
9657 case TEXTURELAYERTYPE_LITTEXTURE:
9658 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9660 // two-pass lit texture with 2x rgbscale
9661 // first the lightmap pass
9662 R_Mesh_TexBind(0, r_texture_white);
9663 R_Mesh_TexMatrix(0, NULL);
9664 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9665 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9666 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9667 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9668 else if (FAKELIGHT_ENABLED)
9669 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9670 else if (rsurface.uselightmaptexture)
9671 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9673 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9674 // then apply the texture to it
9675 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9676 R_Mesh_TexBind(0, layer->texture);
9677 R_Mesh_TexMatrix(0, &layer->texmatrix);
9678 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9679 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9680 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);
9684 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9685 R_Mesh_TexBind(0, layer->texture);
9686 R_Mesh_TexMatrix(0, &layer->texmatrix);
9687 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9688 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9689 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9690 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);
9692 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);
9695 case TEXTURELAYERTYPE_TEXTURE:
9696 // singletexture unlit texture with transparency support
9697 R_Mesh_TexBind(0, layer->texture);
9698 R_Mesh_TexMatrix(0, &layer->texmatrix);
9699 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9700 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9701 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);
9703 case TEXTURELAYERTYPE_FOG:
9704 // singletexture fogging
9707 R_Mesh_TexBind(0, layer->texture);
9708 R_Mesh_TexMatrix(0, &layer->texmatrix);
9709 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9710 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9714 R_Mesh_TexBind(0, 0);
9715 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9717 // generate a color array for the fog pass
9718 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9719 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9723 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9726 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9728 GL_DepthFunc(GL_LEQUAL);
9729 GL_AlphaTest(false);
9733 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9737 r_vertexgeneric_t *batchvertex;
9740 // R_Mesh_ResetTextureState();
9741 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9743 if(rsurface.texture && rsurface.texture->currentskinframe)
9745 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9746 c[3] *= rsurface.texture->currentalpha;
9756 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9758 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9759 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9760 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9763 // brighten it up (as texture value 127 means "unlit")
9764 c[0] *= 2 * r_refdef.view.colorscale;
9765 c[1] *= 2 * r_refdef.view.colorscale;
9766 c[2] *= 2 * r_refdef.view.colorscale;
9768 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9769 c[3] *= r_wateralpha.value;
9771 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9773 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9774 GL_DepthMask(false);
9776 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9778 GL_BlendFunc(GL_ONE, GL_ONE);
9779 GL_DepthMask(false);
9781 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9783 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9784 GL_DepthMask(false);
9786 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9788 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9789 GL_DepthMask(false);
9793 GL_BlendFunc(GL_ONE, GL_ZERO);
9794 GL_DepthMask(writedepth);
9797 if (r_showsurfaces.integer == 3)
9799 rsurface.passcolor4f = NULL;
9801 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9803 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9805 rsurface.passcolor4f = NULL;
9806 rsurface.passcolor4f_vertexbuffer = 0;
9807 rsurface.passcolor4f_bufferoffset = 0;
9809 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9811 qboolean applycolor = true;
9814 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9816 r_refdef.lightmapintensity = 1;
9817 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9818 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9820 else if (FAKELIGHT_ENABLED)
9822 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9824 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9825 RSurf_DrawBatch_GL11_ApplyFakeLight();
9826 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9830 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9832 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9833 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9834 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9837 if(!rsurface.passcolor4f)
9838 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9840 RSurf_DrawBatch_GL11_ApplyAmbient();
9841 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9842 if(r_refdef.fogenabled)
9843 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9844 RSurf_DrawBatch_GL11_ClampColor();
9846 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9847 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9850 else if (!r_refdef.view.showdebug)
9852 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9853 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9854 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9856 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9857 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9859 R_Mesh_PrepareVertices_Generic_Unlock();
9862 else if (r_showsurfaces.integer == 4)
9864 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9865 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9866 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9868 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9869 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9870 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9872 R_Mesh_PrepareVertices_Generic_Unlock();
9875 else if (r_showsurfaces.integer == 2)
9878 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9879 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9880 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9882 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9883 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9884 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9885 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9886 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9887 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9888 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9890 R_Mesh_PrepareVertices_Generic_Unlock();
9891 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9895 int texturesurfaceindex;
9897 const msurface_t *surface;
9898 float surfacecolor4f[4];
9899 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9900 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9902 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9904 surface = texturesurfacelist[texturesurfaceindex];
9905 k = (int)(((size_t)surface) / sizeof(msurface_t));
9906 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9907 for (j = 0;j < surface->num_vertices;j++)
9909 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9910 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9914 R_Mesh_PrepareVertices_Generic_Unlock();
9919 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9922 RSurf_SetupDepthAndCulling();
9923 if (r_showsurfaces.integer)
9925 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9928 switch (vid.renderpath)
9930 case RENDERPATH_GL20:
9931 case RENDERPATH_D3D9:
9932 case RENDERPATH_D3D10:
9933 case RENDERPATH_D3D11:
9934 case RENDERPATH_SOFT:
9935 case RENDERPATH_GLES2:
9936 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9938 case RENDERPATH_GL13:
9939 case RENDERPATH_GLES1:
9940 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9942 case RENDERPATH_GL11:
9943 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9949 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9952 RSurf_SetupDepthAndCulling();
9953 if (r_showsurfaces.integer)
9955 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9958 switch (vid.renderpath)
9960 case RENDERPATH_GL20:
9961 case RENDERPATH_D3D9:
9962 case RENDERPATH_D3D10:
9963 case RENDERPATH_D3D11:
9964 case RENDERPATH_SOFT:
9965 case RENDERPATH_GLES2:
9966 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9968 case RENDERPATH_GL13:
9969 case RENDERPATH_GLES1:
9970 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9972 case RENDERPATH_GL11:
9973 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9979 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9982 int texturenumsurfaces, endsurface;
9984 const msurface_t *surface;
9985 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9987 // if the model is static it doesn't matter what value we give for
9988 // wantnormals and wanttangents, so this logic uses only rules applicable
9989 // to a model, knowing that they are meaningless otherwise
9990 if (ent == r_refdef.scene.worldentity)
9991 RSurf_ActiveWorldEntity();
9992 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9993 RSurf_ActiveModelEntity(ent, false, false, false);
9996 switch (vid.renderpath)
9998 case RENDERPATH_GL20:
9999 case RENDERPATH_D3D9:
10000 case RENDERPATH_D3D10:
10001 case RENDERPATH_D3D11:
10002 case RENDERPATH_SOFT:
10003 case RENDERPATH_GLES2:
10004 RSurf_ActiveModelEntity(ent, true, true, false);
10006 case RENDERPATH_GL11:
10007 case RENDERPATH_GL13:
10008 case RENDERPATH_GLES1:
10009 RSurf_ActiveModelEntity(ent, true, false, false);
10014 if (r_transparentdepthmasking.integer)
10016 qboolean setup = false;
10017 for (i = 0;i < numsurfaces;i = j)
10020 surface = rsurface.modelsurfaces + surfacelist[i];
10021 texture = surface->texture;
10022 rsurface.texture = R_GetCurrentTexture(texture);
10023 rsurface.lightmaptexture = NULL;
10024 rsurface.deluxemaptexture = NULL;
10025 rsurface.uselightmaptexture = false;
10026 // scan ahead until we find a different texture
10027 endsurface = min(i + 1024, numsurfaces);
10028 texturenumsurfaces = 0;
10029 texturesurfacelist[texturenumsurfaces++] = surface;
10030 for (;j < endsurface;j++)
10032 surface = rsurface.modelsurfaces + surfacelist[j];
10033 if (texture != surface->texture)
10035 texturesurfacelist[texturenumsurfaces++] = surface;
10037 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10039 // render the range of surfaces as depth
10043 GL_ColorMask(0,0,0,0);
10045 GL_DepthTest(true);
10046 GL_BlendFunc(GL_ONE, GL_ZERO);
10047 GL_DepthMask(true);
10048 // R_Mesh_ResetTextureState();
10049 R_SetupShader_DepthOrShadow();
10051 RSurf_SetupDepthAndCulling();
10052 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10053 if (rsurface.batchvertex3fbuffer)
10054 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10056 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10060 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10063 for (i = 0;i < numsurfaces;i = j)
10066 surface = rsurface.modelsurfaces + surfacelist[i];
10067 texture = surface->texture;
10068 rsurface.texture = R_GetCurrentTexture(texture);
10069 // scan ahead until we find a different texture
10070 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10071 texturenumsurfaces = 0;
10072 texturesurfacelist[texturenumsurfaces++] = surface;
10073 if(FAKELIGHT_ENABLED)
10075 rsurface.lightmaptexture = NULL;
10076 rsurface.deluxemaptexture = NULL;
10077 rsurface.uselightmaptexture = false;
10078 for (;j < endsurface;j++)
10080 surface = rsurface.modelsurfaces + surfacelist[j];
10081 if (texture != surface->texture)
10083 texturesurfacelist[texturenumsurfaces++] = surface;
10088 rsurface.lightmaptexture = surface->lightmaptexture;
10089 rsurface.deluxemaptexture = surface->deluxemaptexture;
10090 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10091 for (;j < endsurface;j++)
10093 surface = rsurface.modelsurfaces + surfacelist[j];
10094 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10096 texturesurfacelist[texturenumsurfaces++] = surface;
10099 // render the range of surfaces
10100 if (ent == r_refdef.scene.worldentity)
10101 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10103 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10105 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10108 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10110 // transparent surfaces get pushed off into the transparent queue
10111 int surfacelistindex;
10112 const msurface_t *surface;
10113 vec3_t tempcenter, center;
10114 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10116 surface = texturesurfacelist[surfacelistindex];
10117 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10118 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10119 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10120 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10121 if (queueentity->transparent_offset) // transparent offset
10123 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10124 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10125 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10127 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10131 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10133 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10135 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10137 RSurf_SetupDepthAndCulling();
10138 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10139 if (rsurface.batchvertex3fbuffer)
10140 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10142 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10146 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10148 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10151 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10154 if (!rsurface.texture->currentnumlayers)
10156 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10157 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10159 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10161 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10162 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10163 else if (!rsurface.texture->currentnumlayers)
10165 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10167 // in the deferred case, transparent surfaces were queued during prepass
10168 if (!r_shadow_usingdeferredprepass)
10169 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10173 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10174 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10179 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10182 texture_t *texture;
10183 R_FrameData_SetMark();
10184 // break the surface list down into batches by texture and use of lightmapping
10185 for (i = 0;i < numsurfaces;i = j)
10188 // texture is the base texture pointer, rsurface.texture is the
10189 // current frame/skin the texture is directing us to use (for example
10190 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10191 // use skin 1 instead)
10192 texture = surfacelist[i]->texture;
10193 rsurface.texture = R_GetCurrentTexture(texture);
10194 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10196 // if this texture is not the kind we want, skip ahead to the next one
10197 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10201 if(FAKELIGHT_ENABLED || depthonly || prepass)
10203 rsurface.lightmaptexture = NULL;
10204 rsurface.deluxemaptexture = NULL;
10205 rsurface.uselightmaptexture = false;
10206 // simply scan ahead until we find a different texture or lightmap state
10207 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10212 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10213 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10214 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10215 // simply scan ahead until we find a different texture or lightmap state
10216 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10219 // render the range of surfaces
10220 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10222 R_FrameData_ReturnToMark();
10225 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10229 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10232 if (!rsurface.texture->currentnumlayers)
10234 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10235 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10237 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10239 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10240 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10241 else if (!rsurface.texture->currentnumlayers)
10243 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10245 // in the deferred case, transparent surfaces were queued during prepass
10246 if (!r_shadow_usingdeferredprepass)
10247 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10251 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10252 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10257 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10260 texture_t *texture;
10261 R_FrameData_SetMark();
10262 // break the surface list down into batches by texture and use of lightmapping
10263 for (i = 0;i < numsurfaces;i = j)
10266 // texture is the base texture pointer, rsurface.texture is the
10267 // current frame/skin the texture is directing us to use (for example
10268 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10269 // use skin 1 instead)
10270 texture = surfacelist[i]->texture;
10271 rsurface.texture = R_GetCurrentTexture(texture);
10272 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10274 // if this texture is not the kind we want, skip ahead to the next one
10275 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10279 if(FAKELIGHT_ENABLED || depthonly || prepass)
10281 rsurface.lightmaptexture = NULL;
10282 rsurface.deluxemaptexture = NULL;
10283 rsurface.uselightmaptexture = false;
10284 // simply scan ahead until we find a different texture or lightmap state
10285 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10290 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10291 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10292 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10293 // simply scan ahead until we find a different texture or lightmap state
10294 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10297 // render the range of surfaces
10298 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10300 R_FrameData_ReturnToMark();
10303 float locboxvertex3f[6*4*3] =
10305 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10306 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10307 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10308 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10309 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10310 1,0,0, 0,0,0, 0,1,0, 1,1,0
10313 unsigned short locboxelements[6*2*3] =
10318 12,13,14, 12,14,15,
10319 16,17,18, 16,18,19,
10323 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10326 cl_locnode_t *loc = (cl_locnode_t *)ent;
10328 float vertex3f[6*4*3];
10330 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10331 GL_DepthMask(false);
10332 GL_DepthRange(0, 1);
10333 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10334 GL_DepthTest(true);
10335 GL_CullFace(GL_NONE);
10336 R_EntityMatrix(&identitymatrix);
10338 // R_Mesh_ResetTextureState();
10340 i = surfacelist[0];
10341 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10342 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10343 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10344 surfacelist[0] < 0 ? 0.5f : 0.125f);
10346 if (VectorCompare(loc->mins, loc->maxs))
10348 VectorSet(size, 2, 2, 2);
10349 VectorMA(loc->mins, -0.5f, size, mins);
10353 VectorCopy(loc->mins, mins);
10354 VectorSubtract(loc->maxs, loc->mins, size);
10357 for (i = 0;i < 6*4*3;)
10358 for (j = 0;j < 3;j++, i++)
10359 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10361 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10362 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10363 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10366 void R_DrawLocs(void)
10369 cl_locnode_t *loc, *nearestloc;
10371 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10372 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10374 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10375 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10379 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10381 if (decalsystem->decals)
10382 Mem_Free(decalsystem->decals);
10383 memset(decalsystem, 0, sizeof(*decalsystem));
10386 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)
10389 tridecal_t *decals;
10392 // expand or initialize the system
10393 if (decalsystem->maxdecals <= decalsystem->numdecals)
10395 decalsystem_t old = *decalsystem;
10396 qboolean useshortelements;
10397 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10398 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10399 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)));
10400 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10401 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10402 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10403 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10404 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10405 if (decalsystem->numdecals)
10406 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10408 Mem_Free(old.decals);
10409 for (i = 0;i < decalsystem->maxdecals*3;i++)
10410 decalsystem->element3i[i] = i;
10411 if (useshortelements)
10412 for (i = 0;i < decalsystem->maxdecals*3;i++)
10413 decalsystem->element3s[i] = i;
10416 // grab a decal and search for another free slot for the next one
10417 decals = decalsystem->decals;
10418 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10419 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10421 decalsystem->freedecal = i;
10422 if (decalsystem->numdecals <= i)
10423 decalsystem->numdecals = i + 1;
10425 // initialize the decal
10427 decal->triangleindex = triangleindex;
10428 decal->surfaceindex = surfaceindex;
10429 decal->decalsequence = decalsequence;
10430 decal->color4f[0][0] = c0[0];
10431 decal->color4f[0][1] = c0[1];
10432 decal->color4f[0][2] = c0[2];
10433 decal->color4f[0][3] = 1;
10434 decal->color4f[1][0] = c1[0];
10435 decal->color4f[1][1] = c1[1];
10436 decal->color4f[1][2] = c1[2];
10437 decal->color4f[1][3] = 1;
10438 decal->color4f[2][0] = c2[0];
10439 decal->color4f[2][1] = c2[1];
10440 decal->color4f[2][2] = c2[2];
10441 decal->color4f[2][3] = 1;
10442 decal->vertex3f[0][0] = v0[0];
10443 decal->vertex3f[0][1] = v0[1];
10444 decal->vertex3f[0][2] = v0[2];
10445 decal->vertex3f[1][0] = v1[0];
10446 decal->vertex3f[1][1] = v1[1];
10447 decal->vertex3f[1][2] = v1[2];
10448 decal->vertex3f[2][0] = v2[0];
10449 decal->vertex3f[2][1] = v2[1];
10450 decal->vertex3f[2][2] = v2[2];
10451 decal->texcoord2f[0][0] = t0[0];
10452 decal->texcoord2f[0][1] = t0[1];
10453 decal->texcoord2f[1][0] = t1[0];
10454 decal->texcoord2f[1][1] = t1[1];
10455 decal->texcoord2f[2][0] = t2[0];
10456 decal->texcoord2f[2][1] = t2[1];
10457 TriangleNormal(v0, v1, v2, decal->plane);
10458 VectorNormalize(decal->plane);
10459 decal->plane[3] = DotProduct(v0, decal->plane);
10462 extern cvar_t cl_decals_bias;
10463 extern cvar_t cl_decals_models;
10464 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10465 // baseparms, parms, temps
10466 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)
10471 const float *vertex3f;
10472 const float *normal3f;
10474 float points[2][9][3];
10481 e = rsurface.modelelement3i + 3*triangleindex;
10483 vertex3f = rsurface.modelvertex3f;
10484 normal3f = rsurface.modelnormal3f;
10488 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10490 index = 3*e[cornerindex];
10491 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10496 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10498 index = 3*e[cornerindex];
10499 VectorCopy(vertex3f + index, v[cornerindex]);
10504 //TriangleNormal(v[0], v[1], v[2], normal);
10505 //if (DotProduct(normal, localnormal) < 0.0f)
10507 // clip by each of the box planes formed from the projection matrix
10508 // if anything survives, we emit the decal
10509 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]);
10512 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]);
10515 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]);
10518 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]);
10521 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]);
10524 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]);
10527 // some part of the triangle survived, so we have to accept it...
10530 // dynamic always uses the original triangle
10532 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10534 index = 3*e[cornerindex];
10535 VectorCopy(vertex3f + index, v[cornerindex]);
10538 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10540 // convert vertex positions to texcoords
10541 Matrix4x4_Transform(projection, v[cornerindex], temp);
10542 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10543 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10544 // calculate distance fade from the projection origin
10545 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10546 f = bound(0.0f, f, 1.0f);
10547 c[cornerindex][0] = r * f;
10548 c[cornerindex][1] = g * f;
10549 c[cornerindex][2] = b * f;
10550 c[cornerindex][3] = 1.0f;
10551 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10554 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);
10556 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10557 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);
10559 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)
10561 matrix4x4_t projection;
10562 decalsystem_t *decalsystem;
10565 const msurface_t *surface;
10566 const msurface_t *surfaces;
10567 const int *surfacelist;
10568 const texture_t *texture;
10570 int numsurfacelist;
10571 int surfacelistindex;
10574 float localorigin[3];
10575 float localnormal[3];
10576 float localmins[3];
10577 float localmaxs[3];
10580 float planes[6][4];
10583 int bih_triangles_count;
10584 int bih_triangles[256];
10585 int bih_surfaces[256];
10587 decalsystem = &ent->decalsystem;
10588 model = ent->model;
10589 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10591 R_DecalSystem_Reset(&ent->decalsystem);
10595 if (!model->brush.data_leafs && !cl_decals_models.integer)
10597 if (decalsystem->model)
10598 R_DecalSystem_Reset(decalsystem);
10602 if (decalsystem->model != model)
10603 R_DecalSystem_Reset(decalsystem);
10604 decalsystem->model = model;
10606 RSurf_ActiveModelEntity(ent, true, false, false);
10608 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10609 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10610 VectorNormalize(localnormal);
10611 localsize = worldsize*rsurface.inversematrixscale;
10612 localmins[0] = localorigin[0] - localsize;
10613 localmins[1] = localorigin[1] - localsize;
10614 localmins[2] = localorigin[2] - localsize;
10615 localmaxs[0] = localorigin[0] + localsize;
10616 localmaxs[1] = localorigin[1] + localsize;
10617 localmaxs[2] = localorigin[2] + localsize;
10619 //VectorCopy(localnormal, planes[4]);
10620 //VectorVectors(planes[4], planes[2], planes[0]);
10621 AnglesFromVectors(angles, localnormal, NULL, false);
10622 AngleVectors(angles, planes[0], planes[2], planes[4]);
10623 VectorNegate(planes[0], planes[1]);
10624 VectorNegate(planes[2], planes[3]);
10625 VectorNegate(planes[4], planes[5]);
10626 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10627 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10628 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10629 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10630 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10631 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10636 matrix4x4_t forwardprojection;
10637 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10638 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10643 float projectionvector[4][3];
10644 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10645 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10646 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10647 projectionvector[0][0] = planes[0][0] * ilocalsize;
10648 projectionvector[0][1] = planes[1][0] * ilocalsize;
10649 projectionvector[0][2] = planes[2][0] * ilocalsize;
10650 projectionvector[1][0] = planes[0][1] * ilocalsize;
10651 projectionvector[1][1] = planes[1][1] * ilocalsize;
10652 projectionvector[1][2] = planes[2][1] * ilocalsize;
10653 projectionvector[2][0] = planes[0][2] * ilocalsize;
10654 projectionvector[2][1] = planes[1][2] * ilocalsize;
10655 projectionvector[2][2] = planes[2][2] * ilocalsize;
10656 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10657 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10658 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10659 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10663 dynamic = model->surfmesh.isanimated;
10664 numsurfacelist = model->nummodelsurfaces;
10665 surfacelist = model->sortedmodelsurfaces;
10666 surfaces = model->data_surfaces;
10669 bih_triangles_count = -1;
10672 if(model->render_bih.numleafs)
10673 bih = &model->render_bih;
10674 else if(model->collision_bih.numleafs)
10675 bih = &model->collision_bih;
10678 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10679 if(bih_triangles_count == 0)
10681 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10683 if(bih_triangles_count > 0)
10685 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10687 surfaceindex = bih_surfaces[triangleindex];
10688 surface = surfaces + surfaceindex;
10689 texture = surface->texture;
10690 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10692 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10694 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10699 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10701 surfaceindex = surfacelist[surfacelistindex];
10702 surface = surfaces + surfaceindex;
10703 // check cull box first because it rejects more than any other check
10704 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10706 // skip transparent surfaces
10707 texture = surface->texture;
10708 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10710 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10712 numtriangles = surface->num_triangles;
10713 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10714 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10719 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10720 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)
10722 int renderentityindex;
10723 float worldmins[3];
10724 float worldmaxs[3];
10725 entity_render_t *ent;
10727 if (!cl_decals_newsystem.integer)
10730 worldmins[0] = worldorigin[0] - worldsize;
10731 worldmins[1] = worldorigin[1] - worldsize;
10732 worldmins[2] = worldorigin[2] - worldsize;
10733 worldmaxs[0] = worldorigin[0] + worldsize;
10734 worldmaxs[1] = worldorigin[1] + worldsize;
10735 worldmaxs[2] = worldorigin[2] + worldsize;
10737 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10739 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10741 ent = r_refdef.scene.entities[renderentityindex];
10742 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10745 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10749 typedef struct r_decalsystem_splatqueue_s
10751 vec3_t worldorigin;
10752 vec3_t worldnormal;
10758 r_decalsystem_splatqueue_t;
10760 int r_decalsystem_numqueued = 0;
10761 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10763 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)
10765 r_decalsystem_splatqueue_t *queue;
10767 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10770 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10771 VectorCopy(worldorigin, queue->worldorigin);
10772 VectorCopy(worldnormal, queue->worldnormal);
10773 Vector4Set(queue->color, r, g, b, a);
10774 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10775 queue->worldsize = worldsize;
10776 queue->decalsequence = cl.decalsequence++;
10779 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10782 r_decalsystem_splatqueue_t *queue;
10784 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10785 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);
10786 r_decalsystem_numqueued = 0;
10789 extern cvar_t cl_decals_max;
10790 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10793 decalsystem_t *decalsystem = &ent->decalsystem;
10800 if (!decalsystem->numdecals)
10803 if (r_showsurfaces.integer)
10806 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10808 R_DecalSystem_Reset(decalsystem);
10812 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10813 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10815 if (decalsystem->lastupdatetime)
10816 frametime = (cl.time - decalsystem->lastupdatetime);
10819 decalsystem->lastupdatetime = cl.time;
10820 decal = decalsystem->decals;
10821 numdecals = decalsystem->numdecals;
10823 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10825 if (decal->color4f[0][3])
10827 decal->lived += frametime;
10828 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10830 memset(decal, 0, sizeof(*decal));
10831 if (decalsystem->freedecal > i)
10832 decalsystem->freedecal = i;
10836 decal = decalsystem->decals;
10837 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10840 // collapse the array by shuffling the tail decals into the gaps
10843 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10844 decalsystem->freedecal++;
10845 if (decalsystem->freedecal == numdecals)
10847 decal[decalsystem->freedecal] = decal[--numdecals];
10850 decalsystem->numdecals = numdecals;
10852 if (numdecals <= 0)
10854 // if there are no decals left, reset decalsystem
10855 R_DecalSystem_Reset(decalsystem);
10859 extern skinframe_t *decalskinframe;
10860 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10863 decalsystem_t *decalsystem = &ent->decalsystem;
10872 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10875 numdecals = decalsystem->numdecals;
10879 if (r_showsurfaces.integer)
10882 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10884 R_DecalSystem_Reset(decalsystem);
10888 // if the model is static it doesn't matter what value we give for
10889 // wantnormals and wanttangents, so this logic uses only rules applicable
10890 // to a model, knowing that they are meaningless otherwise
10891 if (ent == r_refdef.scene.worldentity)
10892 RSurf_ActiveWorldEntity();
10894 RSurf_ActiveModelEntity(ent, false, false, false);
10896 decalsystem->lastupdatetime = cl.time;
10897 decal = decalsystem->decals;
10899 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10901 // update vertex positions for animated models
10902 v3f = decalsystem->vertex3f;
10903 c4f = decalsystem->color4f;
10904 t2f = decalsystem->texcoord2f;
10905 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10907 if (!decal->color4f[0][3])
10910 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10914 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10917 // update color values for fading decals
10918 if (decal->lived >= cl_decals_time.value)
10919 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10923 c4f[ 0] = decal->color4f[0][0] * alpha;
10924 c4f[ 1] = decal->color4f[0][1] * alpha;
10925 c4f[ 2] = decal->color4f[0][2] * alpha;
10927 c4f[ 4] = decal->color4f[1][0] * alpha;
10928 c4f[ 5] = decal->color4f[1][1] * alpha;
10929 c4f[ 6] = decal->color4f[1][2] * alpha;
10931 c4f[ 8] = decal->color4f[2][0] * alpha;
10932 c4f[ 9] = decal->color4f[2][1] * alpha;
10933 c4f[10] = decal->color4f[2][2] * alpha;
10936 t2f[0] = decal->texcoord2f[0][0];
10937 t2f[1] = decal->texcoord2f[0][1];
10938 t2f[2] = decal->texcoord2f[1][0];
10939 t2f[3] = decal->texcoord2f[1][1];
10940 t2f[4] = decal->texcoord2f[2][0];
10941 t2f[5] = decal->texcoord2f[2][1];
10943 // update vertex positions for animated models
10944 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10946 e = rsurface.modelelement3i + 3*decal->triangleindex;
10947 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10948 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10949 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10953 VectorCopy(decal->vertex3f[0], v3f);
10954 VectorCopy(decal->vertex3f[1], v3f + 3);
10955 VectorCopy(decal->vertex3f[2], v3f + 6);
10958 if (r_refdef.fogenabled)
10960 alpha = RSurf_FogVertex(v3f);
10961 VectorScale(c4f, alpha, c4f);
10962 alpha = RSurf_FogVertex(v3f + 3);
10963 VectorScale(c4f + 4, alpha, c4f + 4);
10964 alpha = RSurf_FogVertex(v3f + 6);
10965 VectorScale(c4f + 8, alpha, c4f + 8);
10976 r_refdef.stats.drawndecals += numtris;
10978 // now render the decals all at once
10979 // (this assumes they all use one particle font texture!)
10980 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);
10981 // R_Mesh_ResetTextureState();
10982 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10983 GL_DepthMask(false);
10984 GL_DepthRange(0, 1);
10985 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10986 GL_DepthTest(true);
10987 GL_CullFace(GL_NONE);
10988 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10989 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10990 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10994 static void R_DrawModelDecals(void)
10998 // fade faster when there are too many decals
10999 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11000 for (i = 0;i < r_refdef.scene.numentities;i++)
11001 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11003 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11004 for (i = 0;i < r_refdef.scene.numentities;i++)
11005 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11006 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11008 R_DecalSystem_ApplySplatEntitiesQueue();
11010 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11011 for (i = 0;i < r_refdef.scene.numentities;i++)
11012 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11014 r_refdef.stats.totaldecals += numdecals;
11016 if (r_showsurfaces.integer)
11019 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11021 for (i = 0;i < r_refdef.scene.numentities;i++)
11023 if (!r_refdef.viewcache.entityvisible[i])
11025 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11026 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11030 extern cvar_t mod_collision_bih;
11031 void R_DrawDebugModel(void)
11033 entity_render_t *ent = rsurface.entity;
11034 int i, j, k, l, flagsmask;
11035 const msurface_t *surface;
11036 dp_model_t *model = ent->model;
11039 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11042 if (r_showoverdraw.value > 0)
11044 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11045 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11046 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11047 GL_DepthTest(false);
11048 GL_DepthMask(false);
11049 GL_DepthRange(0, 1);
11050 GL_BlendFunc(GL_ONE, GL_ONE);
11051 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11053 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11055 rsurface.texture = R_GetCurrentTexture(surface->texture);
11056 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11058 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11059 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11060 if (!rsurface.texture->currentlayers->depthmask)
11061 GL_Color(c, 0, 0, 1.0f);
11062 else if (ent == r_refdef.scene.worldentity)
11063 GL_Color(c, c, c, 1.0f);
11065 GL_Color(0, c, 0, 1.0f);
11066 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11070 rsurface.texture = NULL;
11073 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11075 // R_Mesh_ResetTextureState();
11076 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11077 GL_DepthRange(0, 1);
11078 GL_DepthTest(!r_showdisabledepthtest.integer);
11079 GL_DepthMask(false);
11080 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11082 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11086 qboolean cullbox = ent == r_refdef.scene.worldentity;
11087 const q3mbrush_t *brush;
11088 const bih_t *bih = &model->collision_bih;
11089 const bih_leaf_t *bihleaf;
11090 float vertex3f[3][3];
11091 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11093 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11095 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11097 switch (bihleaf->type)
11100 brush = model->brush.data_brushes + bihleaf->itemindex;
11101 if (brush->colbrushf && brush->colbrushf->numtriangles)
11103 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11104 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11105 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11108 case BIH_COLLISIONTRIANGLE:
11109 triangleindex = bihleaf->itemindex;
11110 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11111 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11112 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11113 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);
11114 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11115 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11117 case BIH_RENDERTRIANGLE:
11118 triangleindex = bihleaf->itemindex;
11119 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11120 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11121 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11122 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);
11123 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11124 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11130 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11132 if (r_showtris.integer && qglPolygonMode)
11134 if (r_showdisabledepthtest.integer)
11136 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11137 GL_DepthMask(false);
11141 GL_BlendFunc(GL_ONE, GL_ZERO);
11142 GL_DepthMask(true);
11144 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11145 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11147 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11149 rsurface.texture = R_GetCurrentTexture(surface->texture);
11150 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11152 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11153 if (!rsurface.texture->currentlayers->depthmask)
11154 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11155 else if (ent == r_refdef.scene.worldentity)
11156 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11158 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11159 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11163 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11164 rsurface.texture = NULL;
11167 if (r_shownormals.value != 0 && qglBegin)
11169 if (r_showdisabledepthtest.integer)
11171 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11172 GL_DepthMask(false);
11176 GL_BlendFunc(GL_ONE, GL_ZERO);
11177 GL_DepthMask(true);
11179 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11181 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11183 rsurface.texture = R_GetCurrentTexture(surface->texture);
11184 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11186 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11187 qglBegin(GL_LINES);
11188 if (r_shownormals.value < 0)
11190 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11192 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11193 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11194 qglVertex3f(v[0], v[1], v[2]);
11195 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11196 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11197 qglVertex3f(v[0], v[1], v[2]);
11200 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11202 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11204 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11205 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11206 qglVertex3f(v[0], v[1], v[2]);
11207 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11208 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11209 qglVertex3f(v[0], v[1], v[2]);
11211 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11213 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11214 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11215 qglVertex3f(v[0], v[1], v[2]);
11216 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11217 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11218 qglVertex3f(v[0], v[1], v[2]);
11220 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11222 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11223 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11224 qglVertex3f(v[0], v[1], v[2]);
11225 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11226 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11227 qglVertex3f(v[0], v[1], v[2]);
11234 rsurface.texture = NULL;
11238 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11239 int r_maxsurfacelist = 0;
11240 const msurface_t **r_surfacelist = NULL;
11241 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11243 int i, j, endj, flagsmask;
11244 dp_model_t *model = r_refdef.scene.worldmodel;
11245 msurface_t *surfaces;
11246 unsigned char *update;
11247 int numsurfacelist = 0;
11251 if (r_maxsurfacelist < model->num_surfaces)
11253 r_maxsurfacelist = model->num_surfaces;
11255 Mem_Free((msurface_t**)r_surfacelist);
11256 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11259 RSurf_ActiveWorldEntity();
11261 surfaces = model->data_surfaces;
11262 update = model->brushq1.lightmapupdateflags;
11264 // update light styles on this submodel
11265 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11267 model_brush_lightstyleinfo_t *style;
11268 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11270 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11272 int *list = style->surfacelist;
11273 style->value = r_refdef.scene.lightstylevalue[style->style];
11274 for (j = 0;j < style->numsurfaces;j++)
11275 update[list[j]] = true;
11280 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11284 R_DrawDebugModel();
11285 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11289 rsurface.lightmaptexture = NULL;
11290 rsurface.deluxemaptexture = NULL;
11291 rsurface.uselightmaptexture = false;
11292 rsurface.texture = NULL;
11293 rsurface.rtlight = NULL;
11294 numsurfacelist = 0;
11295 // add visible surfaces to draw list
11296 for (i = 0;i < model->nummodelsurfaces;i++)
11298 j = model->sortedmodelsurfaces[i];
11299 if (r_refdef.viewcache.world_surfacevisible[j])
11300 r_surfacelist[numsurfacelist++] = surfaces + j;
11302 // update lightmaps if needed
11303 if (model->brushq1.firstrender)
11305 model->brushq1.firstrender = false;
11306 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11308 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11312 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11313 if (r_refdef.viewcache.world_surfacevisible[j])
11315 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11317 // don't do anything if there were no surfaces
11318 if (!numsurfacelist)
11320 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11323 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11325 // add to stats if desired
11326 if (r_speeds.integer && !skysurfaces && !depthonly)
11328 r_refdef.stats.world_surfaces += numsurfacelist;
11329 for (j = 0;j < numsurfacelist;j++)
11330 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11333 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11336 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11338 int i, j, endj, flagsmask;
11339 dp_model_t *model = ent->model;
11340 msurface_t *surfaces;
11341 unsigned char *update;
11342 int numsurfacelist = 0;
11346 if (r_maxsurfacelist < model->num_surfaces)
11348 r_maxsurfacelist = model->num_surfaces;
11350 Mem_Free((msurface_t **)r_surfacelist);
11351 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11354 // if the model is static it doesn't matter what value we give for
11355 // wantnormals and wanttangents, so this logic uses only rules applicable
11356 // to a model, knowing that they are meaningless otherwise
11357 if (ent == r_refdef.scene.worldentity)
11358 RSurf_ActiveWorldEntity();
11359 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11360 RSurf_ActiveModelEntity(ent, false, false, false);
11362 RSurf_ActiveModelEntity(ent, true, true, true);
11363 else if (depthonly)
11365 switch (vid.renderpath)
11367 case RENDERPATH_GL20:
11368 case RENDERPATH_D3D9:
11369 case RENDERPATH_D3D10:
11370 case RENDERPATH_D3D11:
11371 case RENDERPATH_SOFT:
11372 case RENDERPATH_GLES2:
11373 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11375 case RENDERPATH_GL11:
11376 case RENDERPATH_GL13:
11377 case RENDERPATH_GLES1:
11378 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11384 switch (vid.renderpath)
11386 case RENDERPATH_GL20:
11387 case RENDERPATH_D3D9:
11388 case RENDERPATH_D3D10:
11389 case RENDERPATH_D3D11:
11390 case RENDERPATH_SOFT:
11391 case RENDERPATH_GLES2:
11392 RSurf_ActiveModelEntity(ent, true, true, false);
11394 case RENDERPATH_GL11:
11395 case RENDERPATH_GL13:
11396 case RENDERPATH_GLES1:
11397 RSurf_ActiveModelEntity(ent, true, false, false);
11402 surfaces = model->data_surfaces;
11403 update = model->brushq1.lightmapupdateflags;
11405 // update light styles
11406 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11408 model_brush_lightstyleinfo_t *style;
11409 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11411 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11413 int *list = style->surfacelist;
11414 style->value = r_refdef.scene.lightstylevalue[style->style];
11415 for (j = 0;j < style->numsurfaces;j++)
11416 update[list[j]] = true;
11421 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11425 R_DrawDebugModel();
11426 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11430 rsurface.lightmaptexture = NULL;
11431 rsurface.deluxemaptexture = NULL;
11432 rsurface.uselightmaptexture = false;
11433 rsurface.texture = NULL;
11434 rsurface.rtlight = NULL;
11435 numsurfacelist = 0;
11436 // add visible surfaces to draw list
11437 for (i = 0;i < model->nummodelsurfaces;i++)
11438 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11439 // don't do anything if there were no surfaces
11440 if (!numsurfacelist)
11442 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11445 // update lightmaps if needed
11449 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11454 R_BuildLightMap(ent, surfaces + j);
11459 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11461 R_BuildLightMap(ent, surfaces + j);
11462 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11464 // add to stats if desired
11465 if (r_speeds.integer && !skysurfaces && !depthonly)
11467 r_refdef.stats.entities_surfaces += numsurfacelist;
11468 for (j = 0;j < numsurfacelist;j++)
11469 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11472 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11475 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11477 static texture_t texture;
11478 static msurface_t surface;
11479 const msurface_t *surfacelist = &surface;
11481 // fake enough texture and surface state to render this geometry
11483 texture.update_lastrenderframe = -1; // regenerate this texture
11484 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11485 texture.currentskinframe = skinframe;
11486 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11487 texture.offsetmapping = OFFSETMAPPING_OFF;
11488 texture.offsetscale = 1;
11489 texture.specularscalemod = 1;
11490 texture.specularpowermod = 1;
11492 surface.texture = &texture;
11493 surface.num_triangles = numtriangles;
11494 surface.num_firsttriangle = firsttriangle;
11495 surface.num_vertices = numvertices;
11496 surface.num_firstvertex = firstvertex;
11499 rsurface.texture = R_GetCurrentTexture(surface.texture);
11500 rsurface.lightmaptexture = NULL;
11501 rsurface.deluxemaptexture = NULL;
11502 rsurface.uselightmaptexture = false;
11503 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11506 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)
11508 static msurface_t surface;
11509 const msurface_t *surfacelist = &surface;
11511 // fake enough texture and surface state to render this geometry
11512 surface.texture = texture;
11513 surface.num_triangles = numtriangles;
11514 surface.num_firsttriangle = firsttriangle;
11515 surface.num_vertices = numvertices;
11516 surface.num_firstvertex = firstvertex;
11519 rsurface.texture = R_GetCurrentTexture(surface.texture);
11520 rsurface.lightmaptexture = NULL;
11521 rsurface.deluxemaptexture = NULL;
11522 rsurface.uselightmaptexture = false;
11523 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);