2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces, this is not yet finished as multisampling is not used"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
78 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
85 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
86 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
95 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
137 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
138 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
170 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
177 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
178 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
179 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
180 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
182 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
183 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
184 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
185 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
186 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
187 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
188 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
190 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
191 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
192 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
193 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
194 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
195 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
196 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
199 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
201 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
203 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
205 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
207 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
208 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
209 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
210 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
211 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
212 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
213 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
214 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
215 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
217 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
218 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
220 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
222 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
224 extern cvar_t v_glslgamma;
226 extern qboolean v_flipped_state;
228 static struct r_bloomstate_s
233 int bloomwidth, bloomheight;
235 textype_t texturetype;
236 int viewfbo; // used to check if r_viewfbo cvar has changed
238 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
239 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
240 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
242 int screentexturewidth, screentextureheight;
243 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
245 int bloomtexturewidth, bloomtextureheight;
246 rtexture_t *texture_bloom;
248 // arrays for rendering the screen passes
249 float screentexcoord2f[8];
250 float bloomtexcoord2f[8];
251 float offsettexcoord2f[8];
253 r_viewport_t viewport;
257 r_waterstate_t r_waterstate;
259 /// shadow volume bsp struct with automatically growing nodes buffer
262 rtexture_t *r_texture_blanknormalmap;
263 rtexture_t *r_texture_white;
264 rtexture_t *r_texture_grey128;
265 rtexture_t *r_texture_black;
266 rtexture_t *r_texture_notexture;
267 rtexture_t *r_texture_whitecube;
268 rtexture_t *r_texture_normalizationcube;
269 rtexture_t *r_texture_fogattenuation;
270 rtexture_t *r_texture_fogheighttexture;
271 rtexture_t *r_texture_gammaramps;
272 unsigned int r_texture_gammaramps_serial;
273 //rtexture_t *r_texture_fogintensity;
274 rtexture_t *r_texture_reflectcube;
276 // TODO: hash lookups?
277 typedef struct cubemapinfo_s
284 int r_texture_numcubemaps;
285 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
287 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
288 unsigned int r_numqueries;
289 unsigned int r_maxqueries;
291 typedef struct r_qwskincache_s
293 char name[MAX_QPATH];
294 skinframe_t *skinframe;
298 static r_qwskincache_t *r_qwskincache;
299 static int r_qwskincache_size;
301 /// vertex coordinates for a quad that covers the screen exactly
302 extern const float r_screenvertex3f[12];
303 extern const float r_d3dscreenvertex3f[12];
304 const float r_screenvertex3f[12] =
311 const float r_d3dscreenvertex3f[12] =
319 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
322 for (i = 0;i < verts;i++)
333 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
336 for (i = 0;i < verts;i++)
346 // FIXME: move this to client?
349 if (gamemode == GAME_NEHAHRA)
351 Cvar_Set("gl_fogenable", "0");
352 Cvar_Set("gl_fogdensity", "0.2");
353 Cvar_Set("gl_fogred", "0.3");
354 Cvar_Set("gl_foggreen", "0.3");
355 Cvar_Set("gl_fogblue", "0.3");
357 r_refdef.fog_density = 0;
358 r_refdef.fog_red = 0;
359 r_refdef.fog_green = 0;
360 r_refdef.fog_blue = 0;
361 r_refdef.fog_alpha = 1;
362 r_refdef.fog_start = 0;
363 r_refdef.fog_end = 16384;
364 r_refdef.fog_height = 1<<30;
365 r_refdef.fog_fadedepth = 128;
366 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
369 static void R_BuildBlankTextures(void)
371 unsigned char data[4];
372 data[2] = 128; // normal X
373 data[1] = 128; // normal Y
374 data[0] = 255; // normal Z
375 data[3] = 128; // height
376 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 static void R_BuildNoTexture(void)
397 unsigned char pix[16][16][4];
398 // this makes a light grey/dark grey checkerboard texture
399 for (y = 0;y < 16;y++)
401 for (x = 0;x < 16;x++)
403 if ((y < 8) ^ (x < 8))
419 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
422 static void R_BuildWhiteCube(void)
424 unsigned char data[6*1*1*4];
425 memset(data, 255, sizeof(data));
426 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
429 static void R_BuildNormalizationCube(void)
433 vec_t s, t, intensity;
436 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
437 for (side = 0;side < 6;side++)
439 for (y = 0;y < NORMSIZE;y++)
441 for (x = 0;x < NORMSIZE;x++)
443 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
479 intensity = 127.0f / sqrt(DotProduct(v, v));
480 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
481 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
482 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
483 data[((side*64+y)*64+x)*4+3] = 255;
487 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
491 static void R_BuildFogTexture(void)
495 unsigned char data1[FOGWIDTH][4];
496 //unsigned char data2[FOGWIDTH][4];
499 r_refdef.fogmasktable_start = r_refdef.fog_start;
500 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
501 r_refdef.fogmasktable_range = r_refdef.fogrange;
502 r_refdef.fogmasktable_density = r_refdef.fog_density;
504 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
505 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
507 d = (x * r - r_refdef.fogmasktable_start);
508 if(developer_extra.integer)
509 Con_DPrintf("%f ", d);
511 if (r_fog_exp2.integer)
512 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
514 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
515 if(developer_extra.integer)
516 Con_DPrintf(" : %f ", alpha);
517 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
518 if(developer_extra.integer)
519 Con_DPrintf(" = %f\n", alpha);
520 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
523 for (x = 0;x < FOGWIDTH;x++)
525 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
530 //data2[x][0] = 255 - b;
531 //data2[x][1] = 255 - b;
532 //data2[x][2] = 255 - b;
535 if (r_texture_fogattenuation)
537 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
543 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
547 static void R_BuildFogHeightTexture(void)
549 unsigned char *inpixels;
557 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
558 if (r_refdef.fogheighttexturename[0])
559 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
562 r_refdef.fog_height_tablesize = 0;
563 if (r_texture_fogheighttexture)
564 R_FreeTexture(r_texture_fogheighttexture);
565 r_texture_fogheighttexture = NULL;
566 if (r_refdef.fog_height_table2d)
567 Mem_Free(r_refdef.fog_height_table2d);
568 r_refdef.fog_height_table2d = NULL;
569 if (r_refdef.fog_height_table1d)
570 Mem_Free(r_refdef.fog_height_table1d);
571 r_refdef.fog_height_table1d = NULL;
575 r_refdef.fog_height_tablesize = size;
576 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
577 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
578 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
580 // LordHavoc: now the magic - what is that table2d for? it is a cooked
581 // average fog color table accounting for every fog layer between a point
582 // and the camera. (Note: attenuation is handled separately!)
583 for (y = 0;y < size;y++)
585 for (x = 0;x < size;x++)
591 for (j = x;j <= y;j++)
593 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599 for (j = x;j >= y;j--)
601 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
606 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
609 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
612 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
615 //=======================================================================================================================================================
617 static const char *builtinshaderstring =
618 #include "shader_glsl.h"
621 const char *builtinhlslshaderstring =
622 #include "shader_hlsl.h"
625 char *glslshaderstring = NULL;
626 char *hlslshaderstring = NULL;
628 //=======================================================================================================================================================
630 typedef struct shaderpermutationinfo_s
635 shaderpermutationinfo_t;
637 typedef struct shadermodeinfo_s
639 const char *vertexfilename;
640 const char *geometryfilename;
641 const char *fragmentfilename;
647 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
648 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {"#define USEDIFFUSE\n", " diffuse"},
651 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
652 {"#define USEVIEWTINT\n", " viewtint"},
653 {"#define USECOLORMAPPING\n", " colormapping"},
654 {"#define USESATURATION\n", " saturation"},
655 {"#define USEFOGINSIDE\n", " foginside"},
656 {"#define USEFOGOUTSIDE\n", " fogoutside"},
657 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
658 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
659 {"#define USEGAMMARAMPS\n", " gammaramps"},
660 {"#define USECUBEFILTER\n", " cubefilter"},
661 {"#define USEGLOW\n", " glow"},
662 {"#define USEBLOOM\n", " bloom"},
663 {"#define USESPECULAR\n", " specular"},
664 {"#define USEPOSTPROCESSING\n", " postprocessing"},
665 {"#define USEREFLECTION\n", " reflection"},
666 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
667 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
668 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
669 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
670 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
671 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
672 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
673 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
674 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
675 {"#define USEALPHAKILL\n", " alphakill"},
676 {"#define USEREFLECTCUBE\n", " reflectcube"},
677 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
678 {"#define USEBOUNCEGRID\n", " bouncegrid"},
679 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
682 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
683 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
703 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
723 struct r_glsl_permutation_s;
724 typedef struct r_glsl_permutation_s
727 struct r_glsl_permutation_s *hashnext;
729 unsigned int permutation;
731 /// indicates if we have tried compiling this permutation already
733 /// 0 if compilation failed
735 // texture units assigned to each detected uniform
736 int tex_Texture_First;
737 int tex_Texture_Second;
738 int tex_Texture_GammaRamps;
739 int tex_Texture_Normal;
740 int tex_Texture_Color;
741 int tex_Texture_Gloss;
742 int tex_Texture_Glow;
743 int tex_Texture_SecondaryNormal;
744 int tex_Texture_SecondaryColor;
745 int tex_Texture_SecondaryGloss;
746 int tex_Texture_SecondaryGlow;
747 int tex_Texture_Pants;
748 int tex_Texture_Shirt;
749 int tex_Texture_FogHeightTexture;
750 int tex_Texture_FogMask;
751 int tex_Texture_Lightmap;
752 int tex_Texture_Deluxemap;
753 int tex_Texture_Attenuation;
754 int tex_Texture_Cube;
755 int tex_Texture_Refraction;
756 int tex_Texture_Reflection;
757 int tex_Texture_ShadowMap2D;
758 int tex_Texture_CubeProjection;
759 int tex_Texture_ScreenDepth;
760 int tex_Texture_ScreenNormalMap;
761 int tex_Texture_ScreenDiffuse;
762 int tex_Texture_ScreenSpecular;
763 int tex_Texture_ReflectMask;
764 int tex_Texture_ReflectCube;
765 int tex_Texture_BounceGrid;
766 /// locations of detected uniforms in program object, or -1 if not found
767 int loc_Texture_First;
768 int loc_Texture_Second;
769 int loc_Texture_GammaRamps;
770 int loc_Texture_Normal;
771 int loc_Texture_Color;
772 int loc_Texture_Gloss;
773 int loc_Texture_Glow;
774 int loc_Texture_SecondaryNormal;
775 int loc_Texture_SecondaryColor;
776 int loc_Texture_SecondaryGloss;
777 int loc_Texture_SecondaryGlow;
778 int loc_Texture_Pants;
779 int loc_Texture_Shirt;
780 int loc_Texture_FogHeightTexture;
781 int loc_Texture_FogMask;
782 int loc_Texture_Lightmap;
783 int loc_Texture_Deluxemap;
784 int loc_Texture_Attenuation;
785 int loc_Texture_Cube;
786 int loc_Texture_Refraction;
787 int loc_Texture_Reflection;
788 int loc_Texture_ShadowMap2D;
789 int loc_Texture_CubeProjection;
790 int loc_Texture_ScreenDepth;
791 int loc_Texture_ScreenNormalMap;
792 int loc_Texture_ScreenDiffuse;
793 int loc_Texture_ScreenSpecular;
794 int loc_Texture_ReflectMask;
795 int loc_Texture_ReflectCube;
796 int loc_Texture_BounceGrid;
798 int loc_BloomBlur_Parameters;
800 int loc_Color_Ambient;
801 int loc_Color_Diffuse;
802 int loc_Color_Specular;
806 int loc_DeferredColor_Ambient;
807 int loc_DeferredColor_Diffuse;
808 int loc_DeferredColor_Specular;
809 int loc_DeferredMod_Diffuse;
810 int loc_DeferredMod_Specular;
811 int loc_DistortScaleRefractReflect;
814 int loc_FogHeightFade;
816 int loc_FogPlaneViewDist;
817 int loc_FogRangeRecip;
820 int loc_LightPosition;
821 int loc_OffsetMapping_ScaleSteps;
823 int loc_ReflectColor;
824 int loc_ReflectFactor;
825 int loc_ReflectOffset;
826 int loc_RefractColor;
828 int loc_ScreenCenterRefractReflect;
829 int loc_ScreenScaleRefractReflect;
830 int loc_ScreenToDepth;
831 int loc_ShadowMap_Parameters;
832 int loc_ShadowMap_TextureScale;
833 int loc_SpecularPower;
838 int loc_ViewTintColor;
840 int loc_ModelToLight;
842 int loc_BackgroundTexMatrix;
843 int loc_ModelViewProjectionMatrix;
844 int loc_ModelViewMatrix;
845 int loc_PixelToScreenTexCoord;
846 int loc_ModelToReflectCube;
847 int loc_ShadowMapMatrix;
848 int loc_BloomColorSubtract;
849 int loc_NormalmapScrollBlend;
850 int loc_BounceGridMatrix;
851 int loc_BounceGridIntensity;
853 r_glsl_permutation_t;
855 #define SHADERPERMUTATION_HASHSIZE 256
858 // non-degradable "lightweight" shader parameters to keep the permutations simpler
859 // these can NOT degrade! only use for simple stuff
862 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
863 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
864 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
865 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
866 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
867 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
868 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
870 #define SHADERSTATICPARMS_COUNT 7
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
877 qboolean R_CompileShader_CheckStaticParms(void)
879 static int r_compileshader_staticparms_save[1];
880 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
881 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
884 if (r_glsl_saturation_redcompensate.integer)
885 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
886 if (r_glsl_vertextextureblend_usebothalphas.integer)
887 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
888 if (r_shadow_glossexact.integer)
889 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
890 if (r_glsl_postprocess.integer)
892 if (r_glsl_postprocess_uservec1_enable.integer)
893 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
894 if (r_glsl_postprocess_uservec2_enable.integer)
895 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
896 if (r_glsl_postprocess_uservec3_enable.integer)
897 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
898 if (r_glsl_postprocess_uservec4_enable.integer)
899 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
901 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
904 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
905 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
906 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
908 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
909 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
911 shaderstaticparms_count = 0;
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
920 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
923 /// information about each possible shader permutation
924 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
925 /// currently selected permutation
926 r_glsl_permutation_t *r_glsl_permutation;
927 /// storage for permutations linked in the hash table
928 memexpandablearray_t r_glsl_permutationarray;
930 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
932 //unsigned int hashdepth = 0;
933 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
934 r_glsl_permutation_t *p;
935 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
937 if (p->mode == mode && p->permutation == permutation)
939 //if (hashdepth > 10)
940 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
947 p->permutation = permutation;
948 p->hashnext = r_glsl_permutationhash[mode][hashindex];
949 r_glsl_permutationhash[mode][hashindex] = p;
950 //if (hashdepth > 10)
951 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
955 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
958 if (!filename || !filename[0])
960 if (!strcmp(filename, "glsl/default.glsl"))
962 if (!glslshaderstring)
964 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
965 if (glslshaderstring)
966 Con_DPrintf("Loading shaders from file %s...\n", filename);
968 glslshaderstring = (char *)builtinshaderstring;
970 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
971 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
974 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
977 if (printfromdisknotice)
978 Con_DPrintf("from disk %s... ", filename);
984 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
988 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
989 char *vertexstring, *geometrystring, *fragmentstring;
990 char permutationname[256];
991 int vertstrings_count = 0;
992 int geomstrings_count = 0;
993 int fragstrings_count = 0;
994 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1003 permutationname[0] = 0;
1004 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1005 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1006 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1008 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1010 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1011 if(vid.support.gl20shaders130)
1013 vertstrings_list[vertstrings_count++] = "#version 130\n";
1014 geomstrings_list[geomstrings_count++] = "#version 130\n";
1015 fragstrings_list[fragstrings_count++] = "#version 130\n";
1016 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1017 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1018 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1021 // the first pretext is which type of shader to compile as
1022 // (later these will all be bound together as a program object)
1023 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1024 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1025 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1027 // the second pretext is the mode (for example a light source)
1028 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1029 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1030 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1031 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1033 // now add all the permutation pretexts
1034 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1036 if (permutation & (1<<i))
1038 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1039 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1040 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1041 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1045 // keep line numbers correct
1046 vertstrings_list[vertstrings_count++] = "\n";
1047 geomstrings_list[geomstrings_count++] = "\n";
1048 fragstrings_list[fragstrings_count++] = "\n";
1053 R_CompileShader_AddStaticParms(mode, permutation);
1054 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1055 vertstrings_count += shaderstaticparms_count;
1056 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1057 geomstrings_count += shaderstaticparms_count;
1058 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059 fragstrings_count += shaderstaticparms_count;
1061 // now append the shader text itself
1062 vertstrings_list[vertstrings_count++] = vertexstring;
1063 geomstrings_list[geomstrings_count++] = geometrystring;
1064 fragstrings_list[fragstrings_count++] = fragmentstring;
1066 // if any sources were NULL, clear the respective list
1068 vertstrings_count = 0;
1069 if (!geometrystring)
1070 geomstrings_count = 0;
1071 if (!fragmentstring)
1072 fragstrings_count = 0;
1074 // compile the shader program
1075 if (vertstrings_count + geomstrings_count + fragstrings_count)
1076 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1080 qglUseProgram(p->program);CHECKGLERROR
1081 // look up all the uniform variable names we care about, so we don't
1082 // have to look them up every time we set them
1084 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1085 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1086 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1087 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1088 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1089 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1090 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1091 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1092 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1093 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1094 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1095 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1096 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1097 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1098 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1099 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1100 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1101 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1102 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1103 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1104 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1105 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1106 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1107 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1108 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1109 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1110 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1111 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1112 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1113 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1114 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1115 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1116 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1117 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1118 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1119 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1120 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1121 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1122 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1123 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1124 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1125 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1126 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1127 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1128 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1129 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1130 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1131 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1132 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1133 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1134 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1135 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1136 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1137 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1138 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1139 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1140 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1141 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1142 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1143 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1144 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1145 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1146 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1147 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1148 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1149 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1150 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1151 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1152 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1153 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1154 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1155 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1156 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1157 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1158 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1159 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1160 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1161 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1162 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1163 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1164 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1165 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1166 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1167 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1168 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1169 // initialize the samplers to refer to the texture units we use
1170 p->tex_Texture_First = -1;
1171 p->tex_Texture_Second = -1;
1172 p->tex_Texture_GammaRamps = -1;
1173 p->tex_Texture_Normal = -1;
1174 p->tex_Texture_Color = -1;
1175 p->tex_Texture_Gloss = -1;
1176 p->tex_Texture_Glow = -1;
1177 p->tex_Texture_SecondaryNormal = -1;
1178 p->tex_Texture_SecondaryColor = -1;
1179 p->tex_Texture_SecondaryGloss = -1;
1180 p->tex_Texture_SecondaryGlow = -1;
1181 p->tex_Texture_Pants = -1;
1182 p->tex_Texture_Shirt = -1;
1183 p->tex_Texture_FogHeightTexture = -1;
1184 p->tex_Texture_FogMask = -1;
1185 p->tex_Texture_Lightmap = -1;
1186 p->tex_Texture_Deluxemap = -1;
1187 p->tex_Texture_Attenuation = -1;
1188 p->tex_Texture_Cube = -1;
1189 p->tex_Texture_Refraction = -1;
1190 p->tex_Texture_Reflection = -1;
1191 p->tex_Texture_ShadowMap2D = -1;
1192 p->tex_Texture_CubeProjection = -1;
1193 p->tex_Texture_ScreenDepth = -1;
1194 p->tex_Texture_ScreenNormalMap = -1;
1195 p->tex_Texture_ScreenDiffuse = -1;
1196 p->tex_Texture_ScreenSpecular = -1;
1197 p->tex_Texture_ReflectMask = -1;
1198 p->tex_Texture_ReflectCube = -1;
1199 p->tex_Texture_BounceGrid = -1;
1201 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1202 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1203 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1204 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1205 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1206 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1207 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1208 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1209 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1211 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1212 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1213 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1214 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1215 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1216 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1217 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1218 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1219 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1220 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1221 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1222 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1223 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1224 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1225 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1227 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1228 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1229 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1230 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1232 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1235 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1239 Mem_Free(vertexstring);
1241 Mem_Free(geometrystring);
1243 Mem_Free(fragmentstring);
1246 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1248 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1249 if (r_glsl_permutation != perm)
1251 r_glsl_permutation = perm;
1252 if (!r_glsl_permutation->program)
1254 if (!r_glsl_permutation->compiled)
1255 R_GLSL_CompilePermutation(perm, mode, permutation);
1256 if (!r_glsl_permutation->program)
1258 // remove features until we find a valid permutation
1260 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1262 // reduce i more quickly whenever it would not remove any bits
1263 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1264 if (!(permutation & j))
1267 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1268 if (!r_glsl_permutation->compiled)
1269 R_GLSL_CompilePermutation(perm, mode, permutation);
1270 if (r_glsl_permutation->program)
1273 if (i >= SHADERPERMUTATION_COUNT)
1275 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1276 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1277 qglUseProgram(0);CHECKGLERROR
1278 return; // no bit left to clear, entire mode is broken
1283 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1285 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1286 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1287 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1294 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1295 extern D3DCAPS9 vid_d3d9caps;
1298 struct r_hlsl_permutation_s;
1299 typedef struct r_hlsl_permutation_s
1301 /// hash lookup data
1302 struct r_hlsl_permutation_s *hashnext;
1304 unsigned int permutation;
1306 /// indicates if we have tried compiling this permutation already
1308 /// NULL if compilation failed
1309 IDirect3DVertexShader9 *vertexshader;
1310 IDirect3DPixelShader9 *pixelshader;
1312 r_hlsl_permutation_t;
1314 typedef enum D3DVSREGISTER_e
1316 D3DVSREGISTER_TexMatrix = 0, // float4x4
1317 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1318 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1319 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1320 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1321 D3DVSREGISTER_ModelToLight = 20, // float4x4
1322 D3DVSREGISTER_EyePosition = 24,
1323 D3DVSREGISTER_FogPlane = 25,
1324 D3DVSREGISTER_LightDir = 26,
1325 D3DVSREGISTER_LightPosition = 27,
1329 typedef enum D3DPSREGISTER_e
1331 D3DPSREGISTER_Alpha = 0,
1332 D3DPSREGISTER_BloomBlur_Parameters = 1,
1333 D3DPSREGISTER_ClientTime = 2,
1334 D3DPSREGISTER_Color_Ambient = 3,
1335 D3DPSREGISTER_Color_Diffuse = 4,
1336 D3DPSREGISTER_Color_Specular = 5,
1337 D3DPSREGISTER_Color_Glow = 6,
1338 D3DPSREGISTER_Color_Pants = 7,
1339 D3DPSREGISTER_Color_Shirt = 8,
1340 D3DPSREGISTER_DeferredColor_Ambient = 9,
1341 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1342 D3DPSREGISTER_DeferredColor_Specular = 11,
1343 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1344 D3DPSREGISTER_DeferredMod_Specular = 13,
1345 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1346 D3DPSREGISTER_EyePosition = 15, // unused
1347 D3DPSREGISTER_FogColor = 16,
1348 D3DPSREGISTER_FogHeightFade = 17,
1349 D3DPSREGISTER_FogPlane = 18,
1350 D3DPSREGISTER_FogPlaneViewDist = 19,
1351 D3DPSREGISTER_FogRangeRecip = 20,
1352 D3DPSREGISTER_LightColor = 21,
1353 D3DPSREGISTER_LightDir = 22, // unused
1354 D3DPSREGISTER_LightPosition = 23,
1355 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1356 D3DPSREGISTER_PixelSize = 25,
1357 D3DPSREGISTER_ReflectColor = 26,
1358 D3DPSREGISTER_ReflectFactor = 27,
1359 D3DPSREGISTER_ReflectOffset = 28,
1360 D3DPSREGISTER_RefractColor = 29,
1361 D3DPSREGISTER_Saturation = 30,
1362 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1363 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1364 D3DPSREGISTER_ScreenToDepth = 33,
1365 D3DPSREGISTER_ShadowMap_Parameters = 34,
1366 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1367 D3DPSREGISTER_SpecularPower = 36,
1368 D3DPSREGISTER_UserVec1 = 37,
1369 D3DPSREGISTER_UserVec2 = 38,
1370 D3DPSREGISTER_UserVec3 = 39,
1371 D3DPSREGISTER_UserVec4 = 40,
1372 D3DPSREGISTER_ViewTintColor = 41,
1373 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1374 D3DPSREGISTER_BloomColorSubtract = 43,
1375 D3DPSREGISTER_ViewToLight = 44, // float4x4
1376 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1377 D3DPSREGISTER_NormalmapScrollBlend = 52,
1382 /// information about each possible shader permutation
1383 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1384 /// currently selected permutation
1385 r_hlsl_permutation_t *r_hlsl_permutation;
1386 /// storage for permutations linked in the hash table
1387 memexpandablearray_t r_hlsl_permutationarray;
1389 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1391 //unsigned int hashdepth = 0;
1392 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1393 r_hlsl_permutation_t *p;
1394 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1396 if (p->mode == mode && p->permutation == permutation)
1398 //if (hashdepth > 10)
1399 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1404 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1406 p->permutation = permutation;
1407 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1408 r_hlsl_permutationhash[mode][hashindex] = p;
1409 //if (hashdepth > 10)
1410 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1414 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1417 if (!filename || !filename[0])
1419 if (!strcmp(filename, "hlsl/default.hlsl"))
1421 if (!hlslshaderstring)
1423 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1424 if (hlslshaderstring)
1425 Con_DPrintf("Loading shaders from file %s...\n", filename);
1427 hlslshaderstring = (char *)builtinhlslshaderstring;
1429 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1430 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1431 return shaderstring;
1433 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1436 if (printfromdisknotice)
1437 Con_DPrintf("from disk %s... ", filename);
1438 return shaderstring;
1440 return shaderstring;
1444 //#include <d3dx9shader.h>
1445 //#include <d3dx9mesh.h>
1447 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1449 DWORD *vsbin = NULL;
1450 DWORD *psbin = NULL;
1451 fs_offset_t vsbinsize;
1452 fs_offset_t psbinsize;
1453 // IDirect3DVertexShader9 *vs = NULL;
1454 // IDirect3DPixelShader9 *ps = NULL;
1455 ID3DXBuffer *vslog = NULL;
1456 ID3DXBuffer *vsbuffer = NULL;
1457 ID3DXConstantTable *vsconstanttable = NULL;
1458 ID3DXBuffer *pslog = NULL;
1459 ID3DXBuffer *psbuffer = NULL;
1460 ID3DXConstantTable *psconstanttable = NULL;
1463 char temp[MAX_INPUTLINE];
1464 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1465 qboolean debugshader = gl_paranoid.integer != 0;
1466 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1470 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1471 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1473 if ((!vsbin && vertstring) || (!psbin && fragstring))
1475 const char* dllnames_d3dx9 [] =
1499 dllhandle_t d3dx9_dll = NULL;
1500 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1501 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1502 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1503 dllfunction_t d3dx9_dllfuncs[] =
1505 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1506 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1507 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1510 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1512 DWORD shaderflags = 0;
1514 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1515 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1516 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1517 if (vertstring && vertstring[0])
1521 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1522 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1523 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1524 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1527 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1530 vsbinsize = vsbuffer->GetBufferSize();
1531 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1532 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1533 vsbuffer->Release();
1537 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1538 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1542 if (fragstring && fragstring[0])
1546 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1547 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1548 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1549 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1552 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1555 psbinsize = psbuffer->GetBufferSize();
1556 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1557 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1558 psbuffer->Release();
1562 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1563 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1567 Sys_UnloadLibrary(&d3dx9_dll);
1570 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1574 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1575 if (FAILED(vsresult))
1576 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1577 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1578 if (FAILED(psresult))
1579 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1581 // free the shader data
1582 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1583 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1586 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1589 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1590 int vertstring_length = 0;
1591 int geomstring_length = 0;
1592 int fragstring_length = 0;
1594 char *vertexstring, *geometrystring, *fragmentstring;
1595 char *vertstring, *geomstring, *fragstring;
1596 char permutationname[256];
1597 char cachename[256];
1598 int vertstrings_count = 0;
1599 int geomstrings_count = 0;
1600 int fragstrings_count = 0;
1601 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608 p->vertexshader = NULL;
1609 p->pixelshader = NULL;
1611 permutationname[0] = 0;
1613 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1614 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1615 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1617 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1618 strlcat(cachename, "hlsl/", sizeof(cachename));
1620 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1621 vertstrings_count = 0;
1622 geomstrings_count = 0;
1623 fragstrings_count = 0;
1624 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1625 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1626 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1628 // the first pretext is which type of shader to compile as
1629 // (later these will all be bound together as a program object)
1630 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1631 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1632 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1634 // the second pretext is the mode (for example a light source)
1635 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1636 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1637 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1638 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1639 strlcat(cachename, modeinfo->name, sizeof(cachename));
1641 // now add all the permutation pretexts
1642 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1644 if (permutation & (1<<i))
1646 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1647 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1648 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1649 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1650 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1654 // keep line numbers correct
1655 vertstrings_list[vertstrings_count++] = "\n";
1656 geomstrings_list[geomstrings_count++] = "\n";
1657 fragstrings_list[fragstrings_count++] = "\n";
1662 R_CompileShader_AddStaticParms(mode, permutation);
1663 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1664 vertstrings_count += shaderstaticparms_count;
1665 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1666 geomstrings_count += shaderstaticparms_count;
1667 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1668 fragstrings_count += shaderstaticparms_count;
1670 // replace spaces in the cachename with _ characters
1671 for (i = 0;cachename[i];i++)
1672 if (cachename[i] == ' ')
1675 // now append the shader text itself
1676 vertstrings_list[vertstrings_count++] = vertexstring;
1677 geomstrings_list[geomstrings_count++] = geometrystring;
1678 fragstrings_list[fragstrings_count++] = fragmentstring;
1680 // if any sources were NULL, clear the respective list
1682 vertstrings_count = 0;
1683 if (!geometrystring)
1684 geomstrings_count = 0;
1685 if (!fragmentstring)
1686 fragstrings_count = 0;
1688 vertstring_length = 0;
1689 for (i = 0;i < vertstrings_count;i++)
1690 vertstring_length += strlen(vertstrings_list[i]);
1691 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1692 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1693 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1695 geomstring_length = 0;
1696 for (i = 0;i < geomstrings_count;i++)
1697 geomstring_length += strlen(geomstrings_list[i]);
1698 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1699 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1700 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1702 fragstring_length = 0;
1703 for (i = 0;i < fragstrings_count;i++)
1704 fragstring_length += strlen(fragstrings_list[i]);
1705 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1706 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1707 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1709 // try to load the cached shader, or generate one
1710 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1712 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1713 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1715 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1719 Mem_Free(vertstring);
1721 Mem_Free(geomstring);
1723 Mem_Free(fragstring);
1725 Mem_Free(vertexstring);
1727 Mem_Free(geometrystring);
1729 Mem_Free(fragmentstring);
1732 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1737 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1739 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1740 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1741 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1742 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1743 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1744 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1746 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1748 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1749 if (r_hlsl_permutation != perm)
1751 r_hlsl_permutation = perm;
1752 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1754 if (!r_hlsl_permutation->compiled)
1755 R_HLSL_CompilePermutation(perm, mode, permutation);
1756 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1758 // remove features until we find a valid permutation
1760 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1762 // reduce i more quickly whenever it would not remove any bits
1763 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1764 if (!(permutation & j))
1767 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1768 if (!r_hlsl_permutation->compiled)
1769 R_HLSL_CompilePermutation(perm, mode, permutation);
1770 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1773 if (i >= SHADERPERMUTATION_COUNT)
1775 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1776 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1777 return; // no bit left to clear, entire mode is broken
1781 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1782 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1784 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1785 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1786 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1790 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1792 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1793 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1794 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1795 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1798 void R_GLSL_Restart_f(void)
1800 unsigned int i, limit;
1801 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1802 Mem_Free(glslshaderstring);
1803 glslshaderstring = NULL;
1804 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1805 Mem_Free(hlslshaderstring);
1806 hlslshaderstring = NULL;
1807 switch(vid.renderpath)
1809 case RENDERPATH_D3D9:
1812 r_hlsl_permutation_t *p;
1813 r_hlsl_permutation = NULL;
1814 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1815 for (i = 0;i < limit;i++)
1817 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1819 if (p->vertexshader)
1820 IDirect3DVertexShader9_Release(p->vertexshader);
1822 IDirect3DPixelShader9_Release(p->pixelshader);
1823 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1826 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1830 case RENDERPATH_D3D10:
1831 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1833 case RENDERPATH_D3D11:
1834 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1836 case RENDERPATH_GL20:
1837 case RENDERPATH_GLES2:
1839 r_glsl_permutation_t *p;
1840 r_glsl_permutation = NULL;
1841 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1842 for (i = 0;i < limit;i++)
1844 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1846 GL_Backend_FreeProgram(p->program);
1847 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1850 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1853 case RENDERPATH_GL11:
1854 case RENDERPATH_GL13:
1855 case RENDERPATH_GLES1:
1857 case RENDERPATH_SOFT:
1862 void R_GLSL_DumpShader_f(void)
1867 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1870 FS_Print(file, "/* The engine may define the following macros:\n");
1871 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1872 for (i = 0;i < SHADERMODE_COUNT;i++)
1873 FS_Print(file, glslshadermodeinfo[i].pretext);
1874 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1875 FS_Print(file, shaderpermutationinfo[i].pretext);
1876 FS_Print(file, "*/\n");
1877 FS_Print(file, builtinshaderstring);
1879 Con_Printf("glsl/default.glsl written\n");
1882 Con_Printf("failed to write to glsl/default.glsl\n");
1884 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1887 FS_Print(file, "/* The engine may define the following macros:\n");
1888 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889 for (i = 0;i < SHADERMODE_COUNT;i++)
1890 FS_Print(file, hlslshadermodeinfo[i].pretext);
1891 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892 FS_Print(file, shaderpermutationinfo[i].pretext);
1893 FS_Print(file, "*/\n");
1894 FS_Print(file, builtinhlslshaderstring);
1896 Con_Printf("hlsl/default.hlsl written\n");
1899 Con_Printf("failed to write to hlsl/default.hlsl\n");
1902 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1905 texturemode = GL_MODULATE;
1906 switch (vid.renderpath)
1908 case RENDERPATH_D3D9:
1910 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1911 R_Mesh_TexBind(GL20TU_FIRST , first );
1912 R_Mesh_TexBind(GL20TU_SECOND, second);
1915 case RENDERPATH_D3D10:
1916 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918 case RENDERPATH_D3D11:
1919 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1921 case RENDERPATH_GL20:
1922 case RENDERPATH_GLES2:
1923 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1924 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1925 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1927 case RENDERPATH_GL13:
1928 case RENDERPATH_GLES1:
1929 R_Mesh_TexBind(0, first );
1930 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1931 R_Mesh_TexBind(1, second);
1933 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1935 case RENDERPATH_GL11:
1936 R_Mesh_TexBind(0, first );
1938 case RENDERPATH_SOFT:
1939 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1940 R_Mesh_TexBind(GL20TU_FIRST , first );
1941 R_Mesh_TexBind(GL20TU_SECOND, second);
1946 void R_SetupShader_DepthOrShadow(void)
1948 switch (vid.renderpath)
1950 case RENDERPATH_D3D9:
1952 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1955 case RENDERPATH_D3D10:
1956 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958 case RENDERPATH_D3D11:
1959 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961 case RENDERPATH_GL20:
1962 case RENDERPATH_GLES2:
1963 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1965 case RENDERPATH_GL13:
1966 case RENDERPATH_GLES1:
1967 R_Mesh_TexBind(0, 0);
1968 R_Mesh_TexBind(1, 0);
1970 case RENDERPATH_GL11:
1971 R_Mesh_TexBind(0, 0);
1973 case RENDERPATH_SOFT:
1974 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1979 void R_SetupShader_ShowDepth(void)
1981 switch (vid.renderpath)
1983 case RENDERPATH_D3D9:
1985 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1988 case RENDERPATH_D3D10:
1989 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1991 case RENDERPATH_D3D11:
1992 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1994 case RENDERPATH_GL20:
1995 case RENDERPATH_GLES2:
1996 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1998 case RENDERPATH_GL13:
1999 case RENDERPATH_GLES1:
2001 case RENDERPATH_GL11:
2003 case RENDERPATH_SOFT:
2004 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2009 extern qboolean r_shadow_usingdeferredprepass;
2010 extern cvar_t r_shadow_deferred_8bitrange;
2011 extern rtexture_t *r_shadow_attenuationgradienttexture;
2012 extern rtexture_t *r_shadow_attenuation2dtexture;
2013 extern rtexture_t *r_shadow_attenuation3dtexture;
2014 extern qboolean r_shadow_usingshadowmap2d;
2015 extern qboolean r_shadow_usingshadowmaportho;
2016 extern float r_shadow_shadowmap_texturescale[2];
2017 extern float r_shadow_shadowmap_parameters[4];
2018 extern qboolean r_shadow_shadowmapvsdct;
2019 extern qboolean r_shadow_shadowmapsampler;
2020 extern int r_shadow_shadowmappcf;
2021 extern rtexture_t *r_shadow_shadowmap2dtexture;
2022 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2023 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2024 extern matrix4x4_t r_shadow_shadowmapmatrix;
2025 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2026 extern int r_shadow_prepass_width;
2027 extern int r_shadow_prepass_height;
2028 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2029 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2030 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2031 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2032 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2034 #define BLENDFUNC_ALLOWS_COLORMOD 1
2035 #define BLENDFUNC_ALLOWS_FOG 2
2036 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2037 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2038 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2039 static int R_BlendFuncFlags(int src, int dst)
2043 // a blendfunc allows colormod if:
2044 // a) it can never keep the destination pixel invariant, or
2045 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2046 // this is to prevent unintended side effects from colormod
2048 // a blendfunc allows fog if:
2049 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2050 // this is to prevent unintended side effects from fog
2052 // these checks are the output of fogeval.pl
2054 r |= BLENDFUNC_ALLOWS_COLORMOD;
2055 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2057 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2058 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2059 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2062 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2063 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2064 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2065 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2066 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2067 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2068 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2069 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2070 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2072 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2073 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2074 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2075 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2080 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
2082 // select a permutation of the lighting shader appropriate to this
2083 // combination of texture, entity, light source, and fogging, only use the
2084 // minimum features necessary to avoid wasting rendering time in the
2085 // fragment shader on features that are not being used
2086 unsigned int permutation = 0;
2087 unsigned int mode = 0;
2089 static float dummy_colormod[3] = {1, 1, 1};
2090 float *colormod = rsurface.colormod;
2092 matrix4x4_t tempmatrix;
2093 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2094 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2095 permutation |= SHADERPERMUTATION_ALPHAKILL;
2096 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2097 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2098 if (rsurfacepass == RSURFPASS_BACKGROUND)
2100 // distorted background
2101 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2103 mode = SHADERMODE_WATER;
2104 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2106 // this is the right thing to do for wateralpha
2107 GL_BlendFunc(GL_ONE, GL_ZERO);
2108 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2112 // this is the right thing to do for entity alpha
2113 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2117 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2119 mode = SHADERMODE_REFRACTION;
2120 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2121 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2125 mode = SHADERMODE_GENERIC;
2126 permutation |= SHADERPERMUTATION_DIFFUSE;
2127 GL_BlendFunc(GL_ONE, GL_ZERO);
2128 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2131 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2133 if (r_glsl_offsetmapping.integer)
2135 switch(rsurface.texture->offsetmapping)
2137 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2138 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2139 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2140 case OFFSETMAPPING_OFF: break;
2143 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2144 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2145 // normalmap (deferred prepass), may use alpha test on diffuse
2146 mode = SHADERMODE_DEFERREDGEOMETRY;
2147 GL_BlendFunc(GL_ONE, GL_ZERO);
2148 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2150 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2152 if (r_glsl_offsetmapping.integer)
2154 switch(rsurface.texture->offsetmapping)
2156 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2157 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2158 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2159 case OFFSETMAPPING_OFF: break;
2162 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2163 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2165 mode = SHADERMODE_LIGHTSOURCE;
2166 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2167 permutation |= SHADERPERMUTATION_CUBEFILTER;
2168 if (diffusescale > 0)
2169 permutation |= SHADERPERMUTATION_DIFFUSE;
2170 if (specularscale > 0)
2171 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2172 if (r_refdef.fogenabled)
2173 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2174 if (rsurface.texture->colormapping)
2175 permutation |= SHADERPERMUTATION_COLORMAPPING;
2176 if (r_shadow_usingshadowmap2d)
2178 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2179 if(r_shadow_shadowmapvsdct)
2180 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2182 if (r_shadow_shadowmapsampler)
2183 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2184 if (r_shadow_shadowmappcf > 1)
2185 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2186 else if (r_shadow_shadowmappcf)
2187 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2189 if (rsurface.texture->reflectmasktexture)
2190 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2191 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2192 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2194 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2196 if (r_glsl_offsetmapping.integer)
2198 switch(rsurface.texture->offsetmapping)
2200 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2201 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2203 case OFFSETMAPPING_OFF: break;
2206 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2207 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2208 // unshaded geometry (fullbright or ambient model lighting)
2209 mode = SHADERMODE_FLATCOLOR;
2210 ambientscale = diffusescale = specularscale = 0;
2211 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2212 permutation |= SHADERPERMUTATION_GLOW;
2213 if (r_refdef.fogenabled)
2214 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2215 if (rsurface.texture->colormapping)
2216 permutation |= SHADERPERMUTATION_COLORMAPPING;
2217 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2219 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2220 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2222 if (r_shadow_shadowmapsampler)
2223 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2224 if (r_shadow_shadowmappcf > 1)
2225 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2226 else if (r_shadow_shadowmappcf)
2227 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2229 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2230 permutation |= SHADERPERMUTATION_REFLECTION;
2231 if (rsurface.texture->reflectmasktexture)
2232 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2233 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2234 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2236 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2238 if (r_glsl_offsetmapping.integer)
2240 switch(rsurface.texture->offsetmapping)
2242 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2243 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2244 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2245 case OFFSETMAPPING_OFF: break;
2248 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2249 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2250 // directional model lighting
2251 mode = SHADERMODE_LIGHTDIRECTION;
2252 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2253 permutation |= SHADERPERMUTATION_GLOW;
2254 permutation |= SHADERPERMUTATION_DIFFUSE;
2255 if (specularscale > 0)
2256 permutation |= SHADERPERMUTATION_SPECULAR;
2257 if (r_refdef.fogenabled)
2258 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2259 if (rsurface.texture->colormapping)
2260 permutation |= SHADERPERMUTATION_COLORMAPPING;
2261 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2263 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2264 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2266 if (r_shadow_shadowmapsampler)
2267 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2268 if (r_shadow_shadowmappcf > 1)
2269 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2270 else if (r_shadow_shadowmappcf)
2271 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2273 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2274 permutation |= SHADERPERMUTATION_REFLECTION;
2275 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2276 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2277 if (rsurface.texture->reflectmasktexture)
2278 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2279 if (r_shadow_bouncegridtexture)
2281 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2282 if (r_shadow_bouncegriddirectional)
2283 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2285 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2286 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2288 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2290 if (r_glsl_offsetmapping.integer)
2292 switch(rsurface.texture->offsetmapping)
2294 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2295 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2297 case OFFSETMAPPING_OFF: break;
2300 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2301 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2302 // ambient model lighting
2303 mode = SHADERMODE_LIGHTDIRECTION;
2304 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2305 permutation |= SHADERPERMUTATION_GLOW;
2306 if (r_refdef.fogenabled)
2307 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2308 if (rsurface.texture->colormapping)
2309 permutation |= SHADERPERMUTATION_COLORMAPPING;
2310 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2312 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2313 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2315 if (r_shadow_shadowmapsampler)
2316 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2317 if (r_shadow_shadowmappcf > 1)
2318 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2319 else if (r_shadow_shadowmappcf)
2320 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2322 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2323 permutation |= SHADERPERMUTATION_REFLECTION;
2324 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2325 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2326 if (rsurface.texture->reflectmasktexture)
2327 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2328 if (r_shadow_bouncegridtexture)
2330 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2331 if (r_shadow_bouncegriddirectional)
2332 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2334 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2339 if (r_glsl_offsetmapping.integer)
2341 switch(rsurface.texture->offsetmapping)
2343 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2344 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2345 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2346 case OFFSETMAPPING_OFF: break;
2349 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2350 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2352 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2353 permutation |= SHADERPERMUTATION_GLOW;
2354 if (r_refdef.fogenabled)
2355 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2356 if (rsurface.texture->colormapping)
2357 permutation |= SHADERPERMUTATION_COLORMAPPING;
2358 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2360 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2361 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2363 if (r_shadow_shadowmapsampler)
2364 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2365 if (r_shadow_shadowmappcf > 1)
2366 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2367 else if (r_shadow_shadowmappcf)
2368 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2370 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2371 permutation |= SHADERPERMUTATION_REFLECTION;
2372 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2373 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2374 if (rsurface.texture->reflectmasktexture)
2375 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2376 if (FAKELIGHT_ENABLED)
2378 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2379 mode = SHADERMODE_FAKELIGHT;
2380 permutation |= SHADERPERMUTATION_DIFFUSE;
2381 if (specularscale > 0)
2382 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2384 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2386 // deluxemapping (light direction texture)
2387 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2388 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2390 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2391 permutation |= SHADERPERMUTATION_DIFFUSE;
2392 if (specularscale > 0)
2393 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2395 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2397 // fake deluxemapping (uniform light direction in tangentspace)
2398 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2399 permutation |= SHADERPERMUTATION_DIFFUSE;
2400 if (specularscale > 0)
2401 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2403 else if (rsurface.uselightmaptexture)
2405 // ordinary lightmapping (q1bsp, q3bsp)
2406 mode = SHADERMODE_LIGHTMAP;
2410 // ordinary vertex coloring (q3bsp)
2411 mode = SHADERMODE_VERTEXCOLOR;
2413 if (r_shadow_bouncegridtexture)
2415 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2416 if (r_shadow_bouncegriddirectional)
2417 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2419 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2420 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2422 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2423 colormod = dummy_colormod;
2424 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2425 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2426 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2427 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2428 switch(vid.renderpath)
2430 case RENDERPATH_D3D9:
2432 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2433 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2434 R_SetupShader_SetPermutationHLSL(mode, permutation);
2435 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2436 if (mode == SHADERMODE_LIGHTSOURCE)
2438 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2439 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2443 if (mode == SHADERMODE_LIGHTDIRECTION)
2445 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2448 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2449 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2450 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2451 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2452 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2454 if (mode == SHADERMODE_LIGHTSOURCE)
2456 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2457 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2458 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2459 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2460 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2462 // additive passes are only darkened by fog, not tinted
2463 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2464 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2468 if (mode == SHADERMODE_FLATCOLOR)
2470 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2472 else if (mode == SHADERMODE_LIGHTDIRECTION)
2474 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2475 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2476 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2477 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2478 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2479 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2480 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2484 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2485 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2486 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2487 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2488 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490 // additive passes are only darkened by fog, not tinted
2491 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2492 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2494 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2495 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2496 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2497 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2498 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2499 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2501 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2502 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2503 if (mode == SHADERMODE_WATER)
2504 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2506 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2507 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2508 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2509 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2510 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2511 if (rsurface.texture->pantstexture)
2512 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2514 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2515 if (rsurface.texture->shirttexture)
2516 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2518 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2519 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2520 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2521 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2522 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2523 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2524 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2525 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2526 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2527 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2529 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2530 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2532 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2533 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2534 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2535 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2536 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2537 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2538 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2539 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2540 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2541 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2542 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2543 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2544 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2545 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2546 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2547 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2548 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2549 if (rsurfacepass == RSURFPASS_BACKGROUND)
2551 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2552 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2553 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2557 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2559 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2560 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2561 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2562 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2563 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2565 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2566 if (rsurface.rtlight)
2568 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2569 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2574 case RENDERPATH_D3D10:
2575 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2577 case RENDERPATH_D3D11:
2578 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2580 case RENDERPATH_GL20:
2581 case RENDERPATH_GLES2:
2582 if (!vid.useinterleavedarrays)
2584 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2585 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2586 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2587 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2588 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2589 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2590 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2591 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2595 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2596 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2598 R_SetupShader_SetPermutationGLSL(mode, permutation);
2599 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2600 if (mode == SHADERMODE_LIGHTSOURCE)
2602 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2603 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2604 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2605 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2606 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2607 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2609 // additive passes are only darkened by fog, not tinted
2610 if (r_glsl_permutation->loc_FogColor >= 0)
2611 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2612 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2616 if (mode == SHADERMODE_FLATCOLOR)
2618 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2620 else if (mode == SHADERMODE_LIGHTDIRECTION)
2622 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2623 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2624 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2625 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2626 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2627 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2628 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2632 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2633 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2634 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2635 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2636 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2638 // additive passes are only darkened by fog, not tinted
2639 if (r_glsl_permutation->loc_FogColor >= 0)
2641 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2642 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2644 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2646 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2647 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2648 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2649 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2650 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2651 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2652 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2653 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2654 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2656 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2657 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2658 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2659 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2660 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2662 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2663 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2664 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2665 if (r_glsl_permutation->loc_Color_Pants >= 0)
2667 if (rsurface.texture->pantstexture)
2668 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2670 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2672 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2674 if (rsurface.texture->shirttexture)
2675 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2677 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2679 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2680 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2681 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2682 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2683 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2684 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2685 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2687 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2689 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2690 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2691 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2692 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2694 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2695 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2696 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2697 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2698 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2699 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2700 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2701 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2702 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2703 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2704 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2705 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2706 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2707 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2708 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2709 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2710 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2711 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2712 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2713 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2714 if (rsurfacepass == RSURFPASS_BACKGROUND)
2716 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2717 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2718 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2722 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2724 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2725 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2726 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2727 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2728 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2730 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2731 if (rsurface.rtlight)
2733 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2734 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2737 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2740 case RENDERPATH_GL11:
2741 case RENDERPATH_GL13:
2742 case RENDERPATH_GLES1:
2744 case RENDERPATH_SOFT:
2745 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2746 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2747 R_SetupShader_SetPermutationSoft(mode, permutation);
2748 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2749 if (mode == SHADERMODE_LIGHTSOURCE)
2751 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2752 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2753 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2758 // additive passes are only darkened by fog, not tinted
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2760 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2764 if (mode == SHADERMODE_FLATCOLOR)
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2768 else if (mode == SHADERMODE_LIGHTDIRECTION)
2770 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2776 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2782 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2783 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2784 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2786 // additive passes are only darkened by fog, not tinted
2787 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2788 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2790 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2791 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2792 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2793 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2794 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2795 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2796 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2797 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2798 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2799 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2801 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2802 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2803 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2804 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2805 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2807 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2808 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2809 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2810 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2812 if (rsurface.texture->pantstexture)
2813 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2815 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2817 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2819 if (rsurface.texture->shirttexture)
2820 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2822 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2824 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2825 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2826 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2827 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2828 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2829 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2830 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2831 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2832 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2834 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2835 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2837 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2838 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2839 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2840 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2841 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2842 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2843 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2844 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2845 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2846 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2847 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2848 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2849 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2850 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2851 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2852 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2853 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2854 if (rsurfacepass == RSURFPASS_BACKGROUND)
2856 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2857 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2858 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2862 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2864 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2865 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2866 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2867 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2868 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2870 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2871 if (rsurface.rtlight)
2873 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2874 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2881 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2883 // select a permutation of the lighting shader appropriate to this
2884 // combination of texture, entity, light source, and fogging, only use the
2885 // minimum features necessary to avoid wasting rendering time in the
2886 // fragment shader on features that are not being used
2887 unsigned int permutation = 0;
2888 unsigned int mode = 0;
2889 const float *lightcolorbase = rtlight->currentcolor;
2890 float ambientscale = rtlight->ambientscale;
2891 float diffusescale = rtlight->diffusescale;
2892 float specularscale = rtlight->specularscale;
2893 // this is the location of the light in view space
2894 vec3_t viewlightorigin;
2895 // this transforms from view space (camera) to light space (cubemap)
2896 matrix4x4_t viewtolight;
2897 matrix4x4_t lighttoview;
2898 float viewtolight16f[16];
2899 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2901 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2902 if (rtlight->currentcubemap != r_texture_whitecube)
2903 permutation |= SHADERPERMUTATION_CUBEFILTER;
2904 if (diffusescale > 0)
2905 permutation |= SHADERPERMUTATION_DIFFUSE;
2906 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2907 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2908 if (r_shadow_usingshadowmap2d)
2910 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2911 if (r_shadow_shadowmapvsdct)
2912 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2914 if (r_shadow_shadowmapsampler)
2915 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2916 if (r_shadow_shadowmappcf > 1)
2917 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2918 else if (r_shadow_shadowmappcf)
2919 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2921 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2922 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2923 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2924 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2925 switch(vid.renderpath)
2927 case RENDERPATH_D3D9:
2929 R_SetupShader_SetPermutationHLSL(mode, permutation);
2930 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2931 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2932 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2933 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2934 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2935 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2936 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2937 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2938 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2939 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2941 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2942 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2943 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2944 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2945 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2946 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2949 case RENDERPATH_D3D10:
2950 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2952 case RENDERPATH_D3D11:
2953 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2955 case RENDERPATH_GL20:
2956 case RENDERPATH_GLES2:
2957 R_SetupShader_SetPermutationGLSL(mode, permutation);
2958 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2959 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2960 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2961 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2962 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2963 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2964 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2965 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2966 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2967 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2969 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2970 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2971 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2972 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2973 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2974 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2976 case RENDERPATH_GL11:
2977 case RENDERPATH_GL13:
2978 case RENDERPATH_GLES1:
2980 case RENDERPATH_SOFT:
2981 R_SetupShader_SetPermutationGLSL(mode, permutation);
2982 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2983 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2984 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2985 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2986 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2987 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2988 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2989 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2990 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2991 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2993 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2994 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2995 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2996 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2997 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2998 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3003 #define SKINFRAME_HASH 1024
3007 int loadsequence; // incremented each level change
3008 memexpandablearray_t array;
3009 skinframe_t *hash[SKINFRAME_HASH];
3012 r_skinframe_t r_skinframe;
3014 void R_SkinFrame_PrepareForPurge(void)
3016 r_skinframe.loadsequence++;
3017 // wrap it without hitting zero
3018 if (r_skinframe.loadsequence >= 200)
3019 r_skinframe.loadsequence = 1;
3022 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3026 // mark the skinframe as used for the purging code
3027 skinframe->loadsequence = r_skinframe.loadsequence;
3030 void R_SkinFrame_Purge(void)
3034 for (i = 0;i < SKINFRAME_HASH;i++)
3036 for (s = r_skinframe.hash[i];s;s = s->next)
3038 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3040 if (s->merged == s->base)
3042 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3043 R_PurgeTexture(s->stain );s->stain = NULL;
3044 R_PurgeTexture(s->merged);s->merged = NULL;
3045 R_PurgeTexture(s->base );s->base = NULL;
3046 R_PurgeTexture(s->pants );s->pants = NULL;
3047 R_PurgeTexture(s->shirt );s->shirt = NULL;
3048 R_PurgeTexture(s->nmap );s->nmap = NULL;
3049 R_PurgeTexture(s->gloss );s->gloss = NULL;
3050 R_PurgeTexture(s->glow );s->glow = NULL;
3051 R_PurgeTexture(s->fog );s->fog = NULL;
3052 R_PurgeTexture(s->reflect);s->reflect = NULL;
3053 s->loadsequence = 0;
3059 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3061 char basename[MAX_QPATH];
3063 Image_StripImageExtension(name, basename, sizeof(basename));
3065 if( last == NULL ) {
3067 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3068 item = r_skinframe.hash[hashindex];
3073 // linearly search through the hash bucket
3074 for( ; item ; item = item->next ) {
3075 if( !strcmp( item->basename, basename ) ) {
3082 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3086 char basename[MAX_QPATH];
3088 Image_StripImageExtension(name, basename, sizeof(basename));
3090 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3091 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3092 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3096 rtexture_t *dyntexture;
3097 // check whether its a dynamic texture
3098 dyntexture = CL_GetDynTexture( basename );
3099 if (!add && !dyntexture)
3101 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3102 memset(item, 0, sizeof(*item));
3103 strlcpy(item->basename, basename, sizeof(item->basename));
3104 item->base = dyntexture; // either NULL or dyntexture handle
3105 item->textureflags = textureflags;
3106 item->comparewidth = comparewidth;
3107 item->compareheight = compareheight;
3108 item->comparecrc = comparecrc;
3109 item->next = r_skinframe.hash[hashindex];
3110 r_skinframe.hash[hashindex] = item;
3112 else if( item->base == NULL )
3114 rtexture_t *dyntexture;
3115 // check whether its a dynamic texture
3116 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3117 dyntexture = CL_GetDynTexture( basename );
3118 item->base = dyntexture; // either NULL or dyntexture handle
3121 R_SkinFrame_MarkUsed(item);
3125 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3127 unsigned long long avgcolor[5], wsum; \
3135 for(pix = 0; pix < cnt; ++pix) \
3138 for(comp = 0; comp < 3; ++comp) \
3140 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3143 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3145 for(comp = 0; comp < 3; ++comp) \
3146 avgcolor[comp] += getpixel * w; \
3149 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3150 avgcolor[4] += getpixel; \
3152 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3154 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3155 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3156 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3157 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3160 extern cvar_t gl_picmip;
3161 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3164 unsigned char *pixels;
3165 unsigned char *bumppixels;
3166 unsigned char *basepixels = NULL;
3167 int basepixels_width = 0;
3168 int basepixels_height = 0;
3169 skinframe_t *skinframe;
3170 rtexture_t *ddsbase = NULL;
3171 qboolean ddshasalpha = false;
3172 float ddsavgcolor[4];
3173 char basename[MAX_QPATH];
3174 int miplevel = R_PicmipForFlags(textureflags);
3175 int savemiplevel = miplevel;
3178 if (cls.state == ca_dedicated)
3181 // return an existing skinframe if already loaded
3182 // if loading of the first image fails, don't make a new skinframe as it
3183 // would cause all future lookups of this to be missing
3184 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3185 if (skinframe && skinframe->base)
3188 Image_StripImageExtension(name, basename, sizeof(basename));
3190 // check for DDS texture file first
3191 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3193 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3194 if (basepixels == NULL)
3198 // FIXME handle miplevel
3200 if (developer_loading.integer)
3201 Con_Printf("loading skin \"%s\"\n", name);
3203 // we've got some pixels to store, so really allocate this new texture now
3205 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3206 skinframe->stain = NULL;
3207 skinframe->merged = NULL;
3208 skinframe->base = NULL;
3209 skinframe->pants = NULL;
3210 skinframe->shirt = NULL;
3211 skinframe->nmap = NULL;
3212 skinframe->gloss = NULL;
3213 skinframe->glow = NULL;
3214 skinframe->fog = NULL;
3215 skinframe->reflect = NULL;
3216 skinframe->hasalpha = false;
3220 skinframe->base = ddsbase;
3221 skinframe->hasalpha = ddshasalpha;
3222 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3223 if (r_loadfog && skinframe->hasalpha)
3224 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3225 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3229 basepixels_width = image_width;
3230 basepixels_height = image_height;
3231 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3232 if (textureflags & TEXF_ALPHA)
3234 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3236 if (basepixels[j] < 255)
3238 skinframe->hasalpha = true;
3242 if (r_loadfog && skinframe->hasalpha)
3244 // has transparent pixels
3245 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3246 for (j = 0;j < image_width * image_height * 4;j += 4)
3251 pixels[j+3] = basepixels[j+3];
3253 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3257 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3258 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3259 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3260 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3261 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3262 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3267 mymiplevel = savemiplevel;
3268 if (r_loadnormalmap)
3269 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3270 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3278 // _norm is the name used by tenebrae and has been adopted as standard
3279 if (r_loadnormalmap && skinframe->nmap == NULL)
3281 mymiplevel = savemiplevel;
3282 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3284 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3288 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3290 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3291 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3292 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3294 Mem_Free(bumppixels);
3296 else if (r_shadow_bumpscale_basetexture.value > 0)
3298 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3299 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3300 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3303 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3304 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3307 // _luma is supported only for tenebrae compatibility
3308 // _glow is the preferred name
3309 mymiplevel = savemiplevel;
3310 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3312 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3313 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3314 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3315 Mem_Free(pixels);pixels = NULL;
3318 mymiplevel = savemiplevel;
3319 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3321 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3322 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3323 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3328 mymiplevel = savemiplevel;
3329 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3331 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3332 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3333 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3338 mymiplevel = savemiplevel;
3339 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3341 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3342 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3343 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3348 mymiplevel = savemiplevel;
3349 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3351 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3352 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3353 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3359 Mem_Free(basepixels);
3364 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3365 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3368 unsigned char *temp1, *temp2;
3369 skinframe_t *skinframe;
3371 if (cls.state == ca_dedicated)
3374 // if already loaded just return it, otherwise make a new skinframe
3375 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3376 if (skinframe && skinframe->base)
3379 skinframe->stain = NULL;
3380 skinframe->merged = NULL;
3381 skinframe->base = NULL;
3382 skinframe->pants = NULL;
3383 skinframe->shirt = NULL;
3384 skinframe->nmap = NULL;
3385 skinframe->gloss = NULL;
3386 skinframe->glow = NULL;
3387 skinframe->fog = NULL;
3388 skinframe->reflect = NULL;
3389 skinframe->hasalpha = false;
3391 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3395 if (developer_loading.integer)
3396 Con_Printf("loading 32bit skin \"%s\"\n", name);
3398 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3400 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3401 temp2 = temp1 + width * height * 4;
3402 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3403 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3406 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3407 if (textureflags & TEXF_ALPHA)
3409 for (i = 3;i < width * height * 4;i += 4)
3411 if (skindata[i] < 255)
3413 skinframe->hasalpha = true;
3417 if (r_loadfog && skinframe->hasalpha)
3419 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3420 memcpy(fogpixels, skindata, width * height * 4);
3421 for (i = 0;i < width * height * 4;i += 4)
3422 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3423 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3424 Mem_Free(fogpixels);
3428 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3429 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3434 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3438 skinframe_t *skinframe;
3440 if (cls.state == ca_dedicated)
3443 // if already loaded just return it, otherwise make a new skinframe
3444 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3445 if (skinframe && skinframe->base)
3448 skinframe->stain = NULL;
3449 skinframe->merged = NULL;
3450 skinframe->base = NULL;
3451 skinframe->pants = NULL;
3452 skinframe->shirt = NULL;
3453 skinframe->nmap = NULL;
3454 skinframe->gloss = NULL;
3455 skinframe->glow = NULL;
3456 skinframe->fog = NULL;
3457 skinframe->reflect = NULL;
3458 skinframe->hasalpha = false;
3460 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3464 if (developer_loading.integer)
3465 Con_Printf("loading quake skin \"%s\"\n", name);
3467 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3468 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3469 memcpy(skinframe->qpixels, skindata, width*height);
3470 skinframe->qwidth = width;
3471 skinframe->qheight = height;
3474 for (i = 0;i < width * height;i++)
3475 featuresmask |= palette_featureflags[skindata[i]];
3477 skinframe->hasalpha = false;
3478 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3479 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3480 skinframe->qgeneratemerged = true;
3481 skinframe->qgeneratebase = skinframe->qhascolormapping;
3482 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3484 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3485 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3490 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3494 unsigned char *skindata;
3496 if (!skinframe->qpixels)
3499 if (!skinframe->qhascolormapping)
3500 colormapped = false;
3504 if (!skinframe->qgeneratebase)
3509 if (!skinframe->qgeneratemerged)
3513 width = skinframe->qwidth;
3514 height = skinframe->qheight;
3515 skindata = skinframe->qpixels;
3517 if (skinframe->qgeneratenmap)
3519 unsigned char *temp1, *temp2;
3520 skinframe->qgeneratenmap = false;
3521 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3522 temp2 = temp1 + width * height * 4;
3523 // use either a custom palette or the quake palette
3524 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3525 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3526 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3530 if (skinframe->qgenerateglow)
3532 skinframe->qgenerateglow = false;
3533 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3538 skinframe->qgeneratebase = false;
3539 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3540 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3541 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3545 skinframe->qgeneratemerged = false;
3546 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3549 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3551 Mem_Free(skinframe->qpixels);
3552 skinframe->qpixels = NULL;
3556 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3559 skinframe_t *skinframe;
3561 if (cls.state == ca_dedicated)
3564 // if already loaded just return it, otherwise make a new skinframe
3565 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3566 if (skinframe && skinframe->base)
3569 skinframe->stain = NULL;
3570 skinframe->merged = NULL;
3571 skinframe->base = NULL;
3572 skinframe->pants = NULL;
3573 skinframe->shirt = NULL;
3574 skinframe->nmap = NULL;
3575 skinframe->gloss = NULL;
3576 skinframe->glow = NULL;
3577 skinframe->fog = NULL;
3578 skinframe->reflect = NULL;
3579 skinframe->hasalpha = false;
3581 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3585 if (developer_loading.integer)
3586 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3588 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3589 if (textureflags & TEXF_ALPHA)
3591 for (i = 0;i < width * height;i++)
3593 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3595 skinframe->hasalpha = true;
3599 if (r_loadfog && skinframe->hasalpha)
3600 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3603 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3604 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3609 skinframe_t *R_SkinFrame_LoadMissing(void)
3611 skinframe_t *skinframe;
3613 if (cls.state == ca_dedicated)
3616 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3617 skinframe->stain = NULL;
3618 skinframe->merged = NULL;
3619 skinframe->base = NULL;
3620 skinframe->pants = NULL;
3621 skinframe->shirt = NULL;
3622 skinframe->nmap = NULL;
3623 skinframe->gloss = NULL;
3624 skinframe->glow = NULL;
3625 skinframe->fog = NULL;
3626 skinframe->reflect = NULL;
3627 skinframe->hasalpha = false;
3629 skinframe->avgcolor[0] = rand() / RAND_MAX;
3630 skinframe->avgcolor[1] = rand() / RAND_MAX;
3631 skinframe->avgcolor[2] = rand() / RAND_MAX;
3632 skinframe->avgcolor[3] = 1;
3637 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3638 typedef struct suffixinfo_s
3641 qboolean flipx, flipy, flipdiagonal;
3644 static suffixinfo_t suffix[3][6] =
3647 {"px", false, false, false},
3648 {"nx", false, false, false},
3649 {"py", false, false, false},
3650 {"ny", false, false, false},
3651 {"pz", false, false, false},
3652 {"nz", false, false, false}
3655 {"posx", false, false, false},
3656 {"negx", false, false, false},
3657 {"posy", false, false, false},
3658 {"negy", false, false, false},
3659 {"posz", false, false, false},
3660 {"negz", false, false, false}
3663 {"rt", true, false, true},
3664 {"lf", false, true, true},
3665 {"ft", true, true, false},
3666 {"bk", false, false, false},
3667 {"up", true, false, true},
3668 {"dn", true, false, true}
3672 static int componentorder[4] = {0, 1, 2, 3};
3674 rtexture_t *R_LoadCubemap(const char *basename)
3676 int i, j, cubemapsize;
3677 unsigned char *cubemappixels, *image_buffer;
3678 rtexture_t *cubemaptexture;
3680 // must start 0 so the first loadimagepixels has no requested width/height
3682 cubemappixels = NULL;
3683 cubemaptexture = NULL;
3684 // keep trying different suffix groups (posx, px, rt) until one loads
3685 for (j = 0;j < 3 && !cubemappixels;j++)
3687 // load the 6 images in the suffix group
3688 for (i = 0;i < 6;i++)
3690 // generate an image name based on the base and and suffix
3691 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3693 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3695 // an image loaded, make sure width and height are equal
3696 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3698 // if this is the first image to load successfully, allocate the cubemap memory
3699 if (!cubemappixels && image_width >= 1)
3701 cubemapsize = image_width;
3702 // note this clears to black, so unavailable sides are black
3703 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3705 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3707 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3710 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3712 Mem_Free(image_buffer);
3716 // if a cubemap loaded, upload it
3719 if (developer_loading.integer)
3720 Con_Printf("loading cubemap \"%s\"\n", basename);
3722 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3723 Mem_Free(cubemappixels);
3727 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3728 if (developer_loading.integer)
3730 Con_Printf("(tried tried images ");
3731 for (j = 0;j < 3;j++)
3732 for (i = 0;i < 6;i++)
3733 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3734 Con_Print(" and was unable to find any of them).\n");
3737 return cubemaptexture;
3740 rtexture_t *R_GetCubemap(const char *basename)
3743 for (i = 0;i < r_texture_numcubemaps;i++)
3744 if (r_texture_cubemaps[i] != NULL)
3745 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3746 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3747 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3748 return r_texture_whitecube;
3749 r_texture_numcubemaps++;
3750 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3751 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3752 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3753 return r_texture_cubemaps[i]->texture;
3756 void R_FreeCubemap(const char *basename)
3760 for (i = 0;i < r_texture_numcubemaps;i++)
3762 if (r_texture_cubemaps[i] != NULL)
3764 if (r_texture_cubemaps[i]->texture)
3766 if (developer_loading.integer)
3767 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3768 R_FreeTexture(r_texture_cubemaps[i]->texture);
3769 Mem_Free(r_texture_cubemaps[i]);
3770 r_texture_cubemaps[i] = NULL;
3776 void R_FreeCubemaps(void)
3779 for (i = 0;i < r_texture_numcubemaps;i++)
3781 if (developer_loading.integer)
3782 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3783 if (r_texture_cubemaps[i] != NULL)
3785 if (r_texture_cubemaps[i]->texture)
3786 R_FreeTexture(r_texture_cubemaps[i]->texture);
3787 Mem_Free(r_texture_cubemaps[i]);
3790 r_texture_numcubemaps = 0;
3793 void R_Main_FreeViewCache(void)
3795 if (r_refdef.viewcache.entityvisible)
3796 Mem_Free(r_refdef.viewcache.entityvisible);
3797 if (r_refdef.viewcache.world_pvsbits)
3798 Mem_Free(r_refdef.viewcache.world_pvsbits);
3799 if (r_refdef.viewcache.world_leafvisible)
3800 Mem_Free(r_refdef.viewcache.world_leafvisible);
3801 if (r_refdef.viewcache.world_surfacevisible)
3802 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3803 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3806 void R_Main_ResizeViewCache(void)
3808 int numentities = r_refdef.scene.numentities;
3809 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3810 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3811 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3812 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3813 if (r_refdef.viewcache.maxentities < numentities)
3815 r_refdef.viewcache.maxentities = numentities;
3816 if (r_refdef.viewcache.entityvisible)
3817 Mem_Free(r_refdef.viewcache.entityvisible);
3818 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3820 if (r_refdef.viewcache.world_numclusters != numclusters)
3822 r_refdef.viewcache.world_numclusters = numclusters;
3823 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3824 if (r_refdef.viewcache.world_pvsbits)
3825 Mem_Free(r_refdef.viewcache.world_pvsbits);
3826 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3828 if (r_refdef.viewcache.world_numleafs != numleafs)
3830 r_refdef.viewcache.world_numleafs = numleafs;
3831 if (r_refdef.viewcache.world_leafvisible)
3832 Mem_Free(r_refdef.viewcache.world_leafvisible);
3833 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3835 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3837 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3838 if (r_refdef.viewcache.world_surfacevisible)
3839 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3840 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3844 extern rtexture_t *loadingscreentexture;
3845 void gl_main_start(void)
3847 loadingscreentexture = NULL;
3848 r_texture_blanknormalmap = NULL;
3849 r_texture_white = NULL;
3850 r_texture_grey128 = NULL;
3851 r_texture_black = NULL;
3852 r_texture_whitecube = NULL;
3853 r_texture_normalizationcube = NULL;
3854 r_texture_fogattenuation = NULL;
3855 r_texture_fogheighttexture = NULL;
3856 r_texture_gammaramps = NULL;
3857 r_texture_numcubemaps = 0;
3859 r_loaddds = r_texture_dds_load.integer != 0;
3860 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3862 switch(vid.renderpath)
3864 case RENDERPATH_GL20:
3865 case RENDERPATH_D3D9:
3866 case RENDERPATH_D3D10:
3867 case RENDERPATH_D3D11:
3868 case RENDERPATH_SOFT:
3869 case RENDERPATH_GLES2:
3870 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3871 Cvar_SetValueQuick(&gl_combine, 1);
3872 Cvar_SetValueQuick(&r_glsl, 1);
3873 r_loadnormalmap = true;
3877 case RENDERPATH_GL13:
3878 case RENDERPATH_GLES1:
3879 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3880 Cvar_SetValueQuick(&gl_combine, 1);
3881 Cvar_SetValueQuick(&r_glsl, 0);
3882 r_loadnormalmap = false;
3883 r_loadgloss = false;
3886 case RENDERPATH_GL11:
3887 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3888 Cvar_SetValueQuick(&gl_combine, 0);
3889 Cvar_SetValueQuick(&r_glsl, 0);
3890 r_loadnormalmap = false;
3891 r_loadgloss = false;
3897 R_FrameData_Reset();
3901 memset(r_queries, 0, sizeof(r_queries));
3903 r_qwskincache = NULL;
3904 r_qwskincache_size = 0;
3906 // due to caching of texture_t references, the collision cache must be reset
3907 Collision_Cache_Reset(true);
3909 // set up r_skinframe loading system for textures
3910 memset(&r_skinframe, 0, sizeof(r_skinframe));
3911 r_skinframe.loadsequence = 1;
3912 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3914 r_main_texturepool = R_AllocTexturePool();
3915 R_BuildBlankTextures();
3917 if (vid.support.arb_texture_cube_map)
3920 R_BuildNormalizationCube();
3922 r_texture_fogattenuation = NULL;
3923 r_texture_fogheighttexture = NULL;
3924 r_texture_gammaramps = NULL;
3925 //r_texture_fogintensity = NULL;
3926 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3927 memset(&r_waterstate, 0, sizeof(r_waterstate));
3928 r_glsl_permutation = NULL;
3929 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3930 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3931 glslshaderstring = NULL;
3933 r_hlsl_permutation = NULL;
3934 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3935 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3937 hlslshaderstring = NULL;
3938 memset(&r_svbsp, 0, sizeof (r_svbsp));
3940 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3941 r_texture_numcubemaps = 0;
3943 r_refdef.fogmasktable_density = 0;
3946 void gl_main_shutdown(void)
3949 R_FrameData_Reset();
3951 R_Main_FreeViewCache();
3953 switch(vid.renderpath)
3955 case RENDERPATH_GL11:
3956 case RENDERPATH_GL13:
3957 case RENDERPATH_GL20:
3958 case RENDERPATH_GLES1:
3959 case RENDERPATH_GLES2:
3961 qglDeleteQueriesARB(r_maxqueries, r_queries);
3963 case RENDERPATH_D3D9:
3964 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3966 case RENDERPATH_D3D10:
3967 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3969 case RENDERPATH_D3D11:
3970 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3972 case RENDERPATH_SOFT:
3978 memset(r_queries, 0, sizeof(r_queries));
3980 r_qwskincache = NULL;
3981 r_qwskincache_size = 0;
3983 // clear out the r_skinframe state
3984 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3985 memset(&r_skinframe, 0, sizeof(r_skinframe));
3988 Mem_Free(r_svbsp.nodes);
3989 memset(&r_svbsp, 0, sizeof (r_svbsp));
3990 R_FreeTexturePool(&r_main_texturepool);
3991 loadingscreentexture = NULL;
3992 r_texture_blanknormalmap = NULL;
3993 r_texture_white = NULL;
3994 r_texture_grey128 = NULL;
3995 r_texture_black = NULL;
3996 r_texture_whitecube = NULL;
3997 r_texture_normalizationcube = NULL;
3998 r_texture_fogattenuation = NULL;
3999 r_texture_fogheighttexture = NULL;
4000 r_texture_gammaramps = NULL;
4001 r_texture_numcubemaps = 0;
4002 //r_texture_fogintensity = NULL;
4003 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4004 memset(&r_waterstate, 0, sizeof(r_waterstate));
4007 r_glsl_permutation = NULL;
4008 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4009 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4010 glslshaderstring = NULL;
4012 r_hlsl_permutation = NULL;
4013 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4014 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4016 hlslshaderstring = NULL;
4019 extern void CL_ParseEntityLump(char *entitystring);
4020 void gl_main_newmap(void)
4022 // FIXME: move this code to client
4023 char *entities, entname[MAX_QPATH];
4025 Mem_Free(r_qwskincache);
4026 r_qwskincache = NULL;
4027 r_qwskincache_size = 0;
4030 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4031 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4033 CL_ParseEntityLump(entities);
4037 if (cl.worldmodel->brush.entities)
4038 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4040 R_Main_FreeViewCache();
4042 R_FrameData_Reset();
4045 void GL_Main_Init(void)
4047 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4049 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4050 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4051 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4052 if (gamemode == GAME_NEHAHRA)
4054 Cvar_RegisterVariable (&gl_fogenable);
4055 Cvar_RegisterVariable (&gl_fogdensity);
4056 Cvar_RegisterVariable (&gl_fogred);
4057 Cvar_RegisterVariable (&gl_foggreen);
4058 Cvar_RegisterVariable (&gl_fogblue);
4059 Cvar_RegisterVariable (&gl_fogstart);
4060 Cvar_RegisterVariable (&gl_fogend);
4061 Cvar_RegisterVariable (&gl_skyclip);
4063 Cvar_RegisterVariable(&r_motionblur);
4064 Cvar_RegisterVariable(&r_motionblur_maxblur);
4065 Cvar_RegisterVariable(&r_motionblur_bmin);
4066 Cvar_RegisterVariable(&r_motionblur_vmin);
4067 Cvar_RegisterVariable(&r_motionblur_vmax);
4068 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4069 Cvar_RegisterVariable(&r_motionblur_randomize);
4070 Cvar_RegisterVariable(&r_damageblur);
4071 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4072 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4073 Cvar_RegisterVariable(&r_equalize_entities_by);
4074 Cvar_RegisterVariable(&r_equalize_entities_to);
4075 Cvar_RegisterVariable(&r_depthfirst);
4076 Cvar_RegisterVariable(&r_useinfinitefarclip);
4077 Cvar_RegisterVariable(&r_farclip_base);
4078 Cvar_RegisterVariable(&r_farclip_world);
4079 Cvar_RegisterVariable(&r_nearclip);
4080 Cvar_RegisterVariable(&r_deformvertexes);
4081 Cvar_RegisterVariable(&r_transparent);
4082 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4083 Cvar_RegisterVariable(&r_showoverdraw);
4084 Cvar_RegisterVariable(&r_showbboxes);
4085 Cvar_RegisterVariable(&r_showsurfaces);
4086 Cvar_RegisterVariable(&r_showtris);
4087 Cvar_RegisterVariable(&r_shownormals);
4088 Cvar_RegisterVariable(&r_showlighting);
4089 Cvar_RegisterVariable(&r_showshadowvolumes);
4090 Cvar_RegisterVariable(&r_showcollisionbrushes);
4091 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4092 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4093 Cvar_RegisterVariable(&r_showdisabledepthtest);
4094 Cvar_RegisterVariable(&r_drawportals);
4095 Cvar_RegisterVariable(&r_drawentities);
4096 Cvar_RegisterVariable(&r_draw2d);
4097 Cvar_RegisterVariable(&r_drawworld);
4098 Cvar_RegisterVariable(&r_cullentities_trace);
4099 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4100 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4101 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4102 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4103 Cvar_RegisterVariable(&r_drawviewmodel);
4104 Cvar_RegisterVariable(&r_drawexteriormodel);
4105 Cvar_RegisterVariable(&r_speeds);
4106 Cvar_RegisterVariable(&r_fullbrights);
4107 Cvar_RegisterVariable(&r_wateralpha);
4108 Cvar_RegisterVariable(&r_dynamic);
4109 Cvar_RegisterVariable(&r_fakelight);
4110 Cvar_RegisterVariable(&r_fakelight_intensity);
4111 Cvar_RegisterVariable(&r_fullbright);
4112 Cvar_RegisterVariable(&r_shadows);
4113 Cvar_RegisterVariable(&r_shadows_darken);
4114 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4115 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4116 Cvar_RegisterVariable(&r_shadows_throwdistance);
4117 Cvar_RegisterVariable(&r_shadows_throwdirection);
4118 Cvar_RegisterVariable(&r_shadows_focus);
4119 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4120 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4121 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4122 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4123 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4124 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4125 Cvar_RegisterVariable(&r_fog_exp2);
4126 Cvar_RegisterVariable(&r_fog_clear);
4127 Cvar_RegisterVariable(&r_drawfog);
4128 Cvar_RegisterVariable(&r_transparentdepthmasking);
4129 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4130 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4131 Cvar_RegisterVariable(&r_texture_dds_load);
4132 Cvar_RegisterVariable(&r_texture_dds_save);
4133 Cvar_RegisterVariable(&r_textureunits);
4134 Cvar_RegisterVariable(&gl_combine);
4135 Cvar_RegisterVariable(&r_viewfbo);
4136 Cvar_RegisterVariable(&r_viewscale);
4137 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4138 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4139 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4140 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4141 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4142 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4143 Cvar_RegisterVariable(&r_glsl);
4144 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4145 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4146 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4147 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4148 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4149 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4150 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4151 Cvar_RegisterVariable(&r_glsl_postprocess);
4152 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4153 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4154 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4155 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4156 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4157 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4158 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4159 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4161 Cvar_RegisterVariable(&r_water);
4162 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4163 Cvar_RegisterVariable(&r_water_clippingplanebias);
4164 Cvar_RegisterVariable(&r_water_refractdistort);
4165 Cvar_RegisterVariable(&r_water_reflectdistort);
4166 Cvar_RegisterVariable(&r_water_scissormode);
4167 Cvar_RegisterVariable(&r_lerpsprites);
4168 Cvar_RegisterVariable(&r_lerpmodels);
4169 Cvar_RegisterVariable(&r_lerplightstyles);
4170 Cvar_RegisterVariable(&r_waterscroll);
4171 Cvar_RegisterVariable(&r_bloom);
4172 Cvar_RegisterVariable(&r_bloom_colorscale);
4173 Cvar_RegisterVariable(&r_bloom_brighten);
4174 Cvar_RegisterVariable(&r_bloom_blur);
4175 Cvar_RegisterVariable(&r_bloom_resolution);
4176 Cvar_RegisterVariable(&r_bloom_colorexponent);
4177 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4178 Cvar_RegisterVariable(&r_hdr);
4179 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4180 Cvar_RegisterVariable(&r_hdr_glowintensity);
4181 Cvar_RegisterVariable(&r_hdr_range);
4182 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4183 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4184 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4185 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4186 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4187 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4188 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4189 Cvar_RegisterVariable(&developer_texturelogging);
4190 Cvar_RegisterVariable(&gl_lightmaps);
4191 Cvar_RegisterVariable(&r_test);
4192 Cvar_RegisterVariable(&r_glsl_saturation);
4193 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4194 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4195 Cvar_RegisterVariable(&r_framedatasize);
4196 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4197 Cvar_SetValue("r_fullbrights", 0);
4198 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4200 Cvar_RegisterVariable(&r_track_sprites);
4201 Cvar_RegisterVariable(&r_track_sprites_flags);
4202 Cvar_RegisterVariable(&r_track_sprites_scalew);
4203 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4204 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4205 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4206 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4207 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4210 extern void R_Textures_Init(void);
4211 extern void GL_Draw_Init(void);
4212 extern void GL_Main_Init(void);
4213 extern void R_Shadow_Init(void);
4214 extern void R_Sky_Init(void);
4215 extern void GL_Surf_Init(void);
4216 extern void R_Particles_Init(void);
4217 extern void R_Explosion_Init(void);
4218 extern void gl_backend_init(void);
4219 extern void Sbar_Init(void);
4220 extern void R_LightningBeams_Init(void);
4221 extern void Mod_RenderInit(void);
4222 extern void Font_Init(void);
4224 void Render_Init(void)
4237 R_LightningBeams_Init();
4246 extern char *ENGINE_EXTENSIONS;
4249 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4250 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4251 gl_version = (const char *)qglGetString(GL_VERSION);
4252 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4256 if (!gl_platformextensions)
4257 gl_platformextensions = "";
4259 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4260 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4261 Con_Printf("GL_VERSION: %s\n", gl_version);
4262 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4263 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4265 VID_CheckExtensions();
4267 // LordHavoc: report supported extensions
4268 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4270 // clear to black (loading plaque will be seen over this)
4271 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4274 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4278 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4280 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4283 p = r_refdef.view.frustum + i;
4288 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4292 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4296 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4300 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4304 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4308 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4312 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4316 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4324 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4328 for (i = 0;i < numplanes;i++)
4335 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4339 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4343 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4347 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4351 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4355 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4359 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4363 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4371 //==================================================================================
4373 // LordHavoc: this stores temporary data used within the same frame
4375 typedef struct r_framedata_mem_s
4377 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4378 size_t size; // how much usable space
4379 size_t current; // how much space in use
4380 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4381 size_t wantedsize; // how much space was allocated
4382 unsigned char *data; // start of real data (16byte aligned)
4386 static r_framedata_mem_t *r_framedata_mem;
4388 void R_FrameData_Reset(void)
4390 while (r_framedata_mem)
4392 r_framedata_mem_t *next = r_framedata_mem->purge;
4393 Mem_Free(r_framedata_mem);
4394 r_framedata_mem = next;
4398 void R_FrameData_Resize(void)
4401 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4402 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4403 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4405 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4406 newmem->wantedsize = wantedsize;
4407 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4408 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4409 newmem->current = 0;
4411 newmem->purge = r_framedata_mem;
4412 r_framedata_mem = newmem;
4416 void R_FrameData_NewFrame(void)
4418 R_FrameData_Resize();
4419 if (!r_framedata_mem)
4421 // if we ran out of space on the last frame, free the old memory now
4422 while (r_framedata_mem->purge)
4424 // repeatedly remove the second item in the list, leaving only head
4425 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4426 Mem_Free(r_framedata_mem->purge);
4427 r_framedata_mem->purge = next;
4429 // reset the current mem pointer
4430 r_framedata_mem->current = 0;
4431 r_framedata_mem->mark = 0;
4434 void *R_FrameData_Alloc(size_t size)
4438 // align to 16 byte boundary - the data pointer is already aligned, so we
4439 // only need to ensure the size of every allocation is also aligned
4440 size = (size + 15) & ~15;
4442 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4444 // emergency - we ran out of space, allocate more memory
4445 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4446 R_FrameData_Resize();
4449 data = r_framedata_mem->data + r_framedata_mem->current;
4450 r_framedata_mem->current += size;
4452 // count the usage for stats
4453 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4454 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4456 return (void *)data;
4459 void *R_FrameData_Store(size_t size, void *data)
4461 void *d = R_FrameData_Alloc(size);
4463 memcpy(d, data, size);
4467 void R_FrameData_SetMark(void)
4469 if (!r_framedata_mem)
4471 r_framedata_mem->mark = r_framedata_mem->current;
4474 void R_FrameData_ReturnToMark(void)
4476 if (!r_framedata_mem)
4478 r_framedata_mem->current = r_framedata_mem->mark;
4481 //==================================================================================
4483 // LordHavoc: animcache originally written by Echon, rewritten since then
4486 * Animation cache prevents re-generating mesh data for an animated model
4487 * multiple times in one frame for lighting, shadowing, reflections, etc.
4490 void R_AnimCache_Free(void)
4494 void R_AnimCache_ClearCache(void)
4497 entity_render_t *ent;
4499 for (i = 0;i < r_refdef.scene.numentities;i++)
4501 ent = r_refdef.scene.entities[i];
4502 ent->animcache_vertex3f = NULL;
4503 ent->animcache_normal3f = NULL;
4504 ent->animcache_svector3f = NULL;
4505 ent->animcache_tvector3f = NULL;
4506 ent->animcache_vertexmesh = NULL;
4507 ent->animcache_vertex3fbuffer = NULL;
4508 ent->animcache_vertexmeshbuffer = NULL;
4512 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4516 // check if we need the meshbuffers
4517 if (!vid.useinterleavedarrays)
4520 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4521 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4522 // TODO: upload vertex3f buffer?
4523 if (ent->animcache_vertexmesh)
4525 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4526 for (i = 0;i < numvertices;i++)
4527 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4528 if (ent->animcache_svector3f)
4529 for (i = 0;i < numvertices;i++)
4530 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4531 if (ent->animcache_tvector3f)
4532 for (i = 0;i < numvertices;i++)
4533 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4534 if (ent->animcache_normal3f)
4535 for (i = 0;i < numvertices;i++)
4536 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4537 // TODO: upload vertexmeshbuffer?
4541 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4543 dp_model_t *model = ent->model;
4545 // see if it's already cached this frame
4546 if (ent->animcache_vertex3f)
4548 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4549 if (wantnormals || wanttangents)
4551 if (ent->animcache_normal3f)
4552 wantnormals = false;
4553 if (ent->animcache_svector3f)
4554 wanttangents = false;
4555 if (wantnormals || wanttangents)
4557 numvertices = model->surfmesh.num_vertices;
4559 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4562 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4563 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4565 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4566 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4572 // see if this ent is worth caching
4573 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4575 // get some memory for this entity and generate mesh data
4576 numvertices = model->surfmesh.num_vertices;
4577 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4579 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4582 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4583 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4585 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4586 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4591 void R_AnimCache_CacheVisibleEntities(void)
4594 qboolean wantnormals = true;
4595 qboolean wanttangents = !r_showsurfaces.integer;
4597 switch(vid.renderpath)
4599 case RENDERPATH_GL20:
4600 case RENDERPATH_D3D9:
4601 case RENDERPATH_D3D10:
4602 case RENDERPATH_D3D11:
4603 case RENDERPATH_GLES2:
4605 case RENDERPATH_GL11:
4606 case RENDERPATH_GL13:
4607 case RENDERPATH_GLES1:
4608 wanttangents = false;
4610 case RENDERPATH_SOFT:
4614 if (r_shownormals.integer)
4615 wanttangents = wantnormals = true;
4617 // TODO: thread this
4618 // NOTE: R_PrepareRTLights() also caches entities
4620 for (i = 0;i < r_refdef.scene.numentities;i++)
4621 if (r_refdef.viewcache.entityvisible[i])
4622 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4625 //==================================================================================
4627 static void R_View_UpdateEntityLighting (void)
4630 entity_render_t *ent;
4631 vec3_t tempdiffusenormal, avg;
4632 vec_t f, fa, fd, fdd;
4633 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4635 for (i = 0;i < r_refdef.scene.numentities;i++)
4637 ent = r_refdef.scene.entities[i];
4639 // skip unseen models
4640 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4644 if (ent->model && ent->model->brush.num_leafs)
4646 // TODO: use modellight for r_ambient settings on world?
4647 VectorSet(ent->modellight_ambient, 0, 0, 0);
4648 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4649 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4653 // fetch the lighting from the worldmodel data
4654 VectorClear(ent->modellight_ambient);
4655 VectorClear(ent->modellight_diffuse);
4656 VectorClear(tempdiffusenormal);
4657 if (ent->flags & RENDER_LIGHT)
4660 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4662 // complete lightning for lit sprites
4663 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4664 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4666 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4667 org[2] = org[2] + r_overheadsprites_pushback.value;
4668 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4671 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4673 if(ent->flags & RENDER_EQUALIZE)
4675 // first fix up ambient lighting...
4676 if(r_equalize_entities_minambient.value > 0)
4678 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4681 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4682 if(fa < r_equalize_entities_minambient.value * fd)
4685 // fa'/fd' = minambient
4686 // fa'+0.25*fd' = fa+0.25*fd
4688 // fa' = fd' * minambient
4689 // fd'*(0.25+minambient) = fa+0.25*fd
4691 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4692 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4694 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4695 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
4696 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4697 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4702 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4704 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4705 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4709 // adjust brightness and saturation to target
4710 avg[0] = avg[1] = avg[2] = fa / f;
4711 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4712 avg[0] = avg[1] = avg[2] = fd / f;
4713 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4719 VectorSet(ent->modellight_ambient, 1, 1, 1);
4721 // move the light direction into modelspace coordinates for lighting code
4722 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4723 if(VectorLength2(ent->modellight_lightdir) == 0)
4724 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4725 VectorNormalize(ent->modellight_lightdir);
4729 #define MAX_LINEOFSIGHTTRACES 64
4731 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4734 vec3_t boxmins, boxmaxs;
4737 dp_model_t *model = r_refdef.scene.worldmodel;
4739 if (!model || !model->brush.TraceLineOfSight)
4742 // expand the box a little
4743 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4744 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4745 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4746 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4747 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4748 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4750 // return true if eye is inside enlarged box
4751 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4755 VectorCopy(eye, start);
4756 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4757 if (model->brush.TraceLineOfSight(model, start, end))
4760 // try various random positions
4761 for (i = 0;i < numsamples;i++)
4763 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4764 if (model->brush.TraceLineOfSight(model, start, end))
4772 static void R_View_UpdateEntityVisible (void)
4777 entity_render_t *ent;
4779 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4780 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4781 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4782 : RENDER_EXTERIORMODEL;
4783 if (!r_drawviewmodel.integer)
4784 renderimask |= RENDER_VIEWMODEL;
4785 if (!r_drawexteriormodel.integer)
4786 renderimask |= RENDER_EXTERIORMODEL;
4787 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4789 // worldmodel can check visibility
4790 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4791 for (i = 0;i < r_refdef.scene.numentities;i++)
4793 ent = r_refdef.scene.entities[i];
4794 if (!(ent->flags & renderimask))
4795 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)))
4796 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))
4797 r_refdef.viewcache.entityvisible[i] = true;
4802 // no worldmodel or it can't check visibility
4803 for (i = 0;i < r_refdef.scene.numentities;i++)
4805 ent = r_refdef.scene.entities[i];
4806 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));
4809 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4810 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4812 for (i = 0;i < r_refdef.scene.numentities;i++)
4814 if (!r_refdef.viewcache.entityvisible[i])
4816 ent = r_refdef.scene.entities[i];
4817 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4819 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4821 continue; // temp entities do pvs only
4822 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4823 ent->last_trace_visibility = realtime;
4824 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4825 r_refdef.viewcache.entityvisible[i] = 0;
4831 /// only used if skyrendermasked, and normally returns false
4832 int R_DrawBrushModelsSky (void)
4835 entity_render_t *ent;
4838 for (i = 0;i < r_refdef.scene.numentities;i++)
4840 if (!r_refdef.viewcache.entityvisible[i])
4842 ent = r_refdef.scene.entities[i];
4843 if (!ent->model || !ent->model->DrawSky)
4845 ent->model->DrawSky(ent);
4851 static void R_DrawNoModel(entity_render_t *ent);
4852 static void R_DrawModels(void)
4855 entity_render_t *ent;
4857 for (i = 0;i < r_refdef.scene.numentities;i++)
4859 if (!r_refdef.viewcache.entityvisible[i])
4861 ent = r_refdef.scene.entities[i];
4862 r_refdef.stats.entities++;
4864 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4867 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4868 Con_Printf("R_DrawModels\n");
4869 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]);
4870 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);
4871 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);
4874 if (ent->model && ent->model->Draw != NULL)
4875 ent->model->Draw(ent);
4881 static void R_DrawModelsDepth(void)
4884 entity_render_t *ent;
4886 for (i = 0;i < r_refdef.scene.numentities;i++)
4888 if (!r_refdef.viewcache.entityvisible[i])
4890 ent = r_refdef.scene.entities[i];
4891 if (ent->model && ent->model->DrawDepth != NULL)
4892 ent->model->DrawDepth(ent);
4896 static void R_DrawModelsDebug(void)
4899 entity_render_t *ent;
4901 for (i = 0;i < r_refdef.scene.numentities;i++)
4903 if (!r_refdef.viewcache.entityvisible[i])
4905 ent = r_refdef.scene.entities[i];
4906 if (ent->model && ent->model->DrawDebug != NULL)
4907 ent->model->DrawDebug(ent);
4911 static void R_DrawModelsAddWaterPlanes(void)
4914 entity_render_t *ent;
4916 for (i = 0;i < r_refdef.scene.numentities;i++)
4918 if (!r_refdef.viewcache.entityvisible[i])
4920 ent = r_refdef.scene.entities[i];
4921 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4922 ent->model->DrawAddWaterPlanes(ent);
4926 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4928 if (r_hdr_irisadaptation.integer)
4932 vec3_t diffusenormal;
4937 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4938 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4939 brightness = max(0.0000001f, brightness);
4940 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4941 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4942 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4943 current = r_hdr_irisadaptation_value.value;
4945 current = min(current + adjust, goal);
4946 else if (current > goal)
4947 current = max(current - adjust, goal);
4948 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4949 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4951 else if (r_hdr_irisadaptation_value.value != 1.0f)
4952 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4955 static void R_View_SetFrustum(const int *scissor)
4958 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4959 vec3_t forward, left, up, origin, v;
4963 // flipped x coordinates (because x points left here)
4964 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4965 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4967 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4968 switch(vid.renderpath)
4970 case RENDERPATH_D3D9:
4971 case RENDERPATH_D3D10:
4972 case RENDERPATH_D3D11:
4973 // non-flipped y coordinates
4974 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4975 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4977 case RENDERPATH_SOFT:
4978 case RENDERPATH_GL11:
4979 case RENDERPATH_GL13:
4980 case RENDERPATH_GL20:
4981 case RENDERPATH_GLES1:
4982 case RENDERPATH_GLES2:
4983 // non-flipped y coordinates
4984 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4985 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4990 // we can't trust r_refdef.view.forward and friends in reflected scenes
4991 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4994 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4995 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4996 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4997 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4998 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4999 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5000 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5001 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5002 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5003 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5004 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5005 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5009 zNear = r_refdef.nearclip;
5010 nudge = 1.0 - 1.0 / (1<<23);
5011 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5012 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5013 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5014 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5015 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5016 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5017 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5018 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5024 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5025 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5026 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5027 r_refdef.view.frustum[0].dist = m[15] - m[12];
5029 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5030 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5031 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5032 r_refdef.view.frustum[1].dist = m[15] + m[12];
5034 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5035 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5036 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5037 r_refdef.view.frustum[2].dist = m[15] - m[13];
5039 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5040 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5041 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5042 r_refdef.view.frustum[3].dist = m[15] + m[13];
5044 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5045 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5046 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5047 r_refdef.view.frustum[4].dist = m[15] - m[14];
5049 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5050 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5051 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5052 r_refdef.view.frustum[5].dist = m[15] + m[14];
5055 if (r_refdef.view.useperspective)
5057 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5058 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]);
5059 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]);
5060 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]);
5061 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]);
5063 // then the normals from the corners relative to origin
5064 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5065 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5066 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5067 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5069 // in a NORMAL view, forward cross left == up
5070 // in a REFLECTED view, forward cross left == down
5071 // so our cross products above need to be adjusted for a left handed coordinate system
5072 CrossProduct(forward, left, v);
5073 if(DotProduct(v, up) < 0)
5075 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5076 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5077 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5078 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5081 // Leaving those out was a mistake, those were in the old code, and they
5082 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5083 // I couldn't reproduce it after adding those normalizations. --blub
5084 VectorNormalize(r_refdef.view.frustum[0].normal);
5085 VectorNormalize(r_refdef.view.frustum[1].normal);
5086 VectorNormalize(r_refdef.view.frustum[2].normal);
5087 VectorNormalize(r_refdef.view.frustum[3].normal);
5089 // make the corners absolute
5090 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5091 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5092 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5093 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5096 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5098 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5099 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5100 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5101 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5102 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5106 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5107 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5108 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5109 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5110 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5111 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5112 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5113 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5114 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5115 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5117 r_refdef.view.numfrustumplanes = 5;
5119 if (r_refdef.view.useclipplane)
5121 r_refdef.view.numfrustumplanes = 6;
5122 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5125 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5126 PlaneClassify(r_refdef.view.frustum + i);
5128 // LordHavoc: note to all quake engine coders, Quake had a special case
5129 // for 90 degrees which assumed a square view (wrong), so I removed it,
5130 // Quake2 has it disabled as well.
5132 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5133 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5134 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5135 //PlaneClassify(&frustum[0]);
5137 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5138 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5139 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5140 //PlaneClassify(&frustum[1]);
5142 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5143 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5144 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5145 //PlaneClassify(&frustum[2]);
5147 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5148 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5149 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5150 //PlaneClassify(&frustum[3]);
5153 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5154 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5155 //PlaneClassify(&frustum[4]);
5158 void R_View_UpdateWithScissor(const int *myscissor)
5160 R_Main_ResizeViewCache();
5161 R_View_SetFrustum(myscissor);
5162 R_View_WorldVisibility(r_refdef.view.useclipplane);
5163 R_View_UpdateEntityVisible();
5164 R_View_UpdateEntityLighting();
5167 void R_View_Update(void)
5169 R_Main_ResizeViewCache();
5170 R_View_SetFrustum(NULL);
5171 R_View_WorldVisibility(r_refdef.view.useclipplane);
5172 R_View_UpdateEntityVisible();
5173 R_View_UpdateEntityLighting();
5176 float viewscalefpsadjusted = 1.0f;
5178 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5180 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5181 scale = bound(0.03125f, scale, 1.0f);
5182 *outwidth = (int)ceil(width * scale);
5183 *outheight = (int)ceil(height * scale);
5186 void R_Mesh_SetMainRenderTargets(void)
5188 if (r_bloomstate.fbo_framebuffer)
5189 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5191 R_Mesh_ResetRenderTargets();
5194 void R_SetupView(qboolean allowwaterclippingplane)
5196 const float *customclipplane = NULL;
5198 int scaledwidth, scaledheight;
5199 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5201 // LordHavoc: couldn't figure out how to make this approach the
5202 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5203 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5204 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5205 dist = r_refdef.view.clipplane.dist;
5206 plane[0] = r_refdef.view.clipplane.normal[0];
5207 plane[1] = r_refdef.view.clipplane.normal[1];
5208 plane[2] = r_refdef.view.clipplane.normal[2];
5210 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5213 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5214 if (!r_refdef.view.useperspective)
5215 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);
5216 else if (vid.stencil && r_useinfinitefarclip.integer)
5217 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);
5219 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);
5220 R_Mesh_SetMainRenderTargets();
5221 R_SetViewport(&r_refdef.view.viewport);
5222 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5224 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5225 float screenplane[4];
5226 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5227 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5228 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5229 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5230 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5234 void R_EntityMatrix(const matrix4x4_t *matrix)
5236 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5238 gl_modelmatrixchanged = false;
5239 gl_modelmatrix = *matrix;
5240 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5241 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5242 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5243 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5245 switch(vid.renderpath)
5247 case RENDERPATH_D3D9:
5249 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5250 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5253 case RENDERPATH_D3D10:
5254 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5256 case RENDERPATH_D3D11:
5257 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5259 case RENDERPATH_GL11:
5260 case RENDERPATH_GL13:
5261 case RENDERPATH_GLES1:
5262 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5264 case RENDERPATH_SOFT:
5265 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5266 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5268 case RENDERPATH_GL20:
5269 case RENDERPATH_GLES2:
5270 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5271 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5277 void R_ResetViewRendering2D(void)
5279 r_viewport_t viewport;
5282 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5283 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);
5284 R_Mesh_ResetRenderTargets();
5285 R_SetViewport(&viewport);
5286 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5287 GL_Color(1, 1, 1, 1);
5288 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5289 GL_BlendFunc(GL_ONE, GL_ZERO);
5290 GL_ScissorTest(false);
5291 GL_DepthMask(false);
5292 GL_DepthRange(0, 1);
5293 GL_DepthTest(false);
5294 GL_DepthFunc(GL_LEQUAL);
5295 R_EntityMatrix(&identitymatrix);
5296 R_Mesh_ResetTextureState();
5297 GL_PolygonOffset(0, 0);
5298 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5299 switch(vid.renderpath)
5301 case RENDERPATH_GL11:
5302 case RENDERPATH_GL13:
5303 case RENDERPATH_GL20:
5304 case RENDERPATH_GLES1:
5305 case RENDERPATH_GLES2:
5306 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5308 case RENDERPATH_D3D9:
5309 case RENDERPATH_D3D10:
5310 case RENDERPATH_D3D11:
5311 case RENDERPATH_SOFT:
5314 GL_CullFace(GL_NONE);
5317 void R_ResetViewRendering3D(void)
5322 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5323 GL_Color(1, 1, 1, 1);
5324 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5325 GL_BlendFunc(GL_ONE, GL_ZERO);
5326 GL_ScissorTest(true);
5328 GL_DepthRange(0, 1);
5330 GL_DepthFunc(GL_LEQUAL);
5331 R_EntityMatrix(&identitymatrix);
5332 R_Mesh_ResetTextureState();
5333 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5334 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5335 switch(vid.renderpath)
5337 case RENDERPATH_GL11:
5338 case RENDERPATH_GL13:
5339 case RENDERPATH_GL20:
5340 case RENDERPATH_GLES1:
5341 case RENDERPATH_GLES2:
5342 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5344 case RENDERPATH_D3D9:
5345 case RENDERPATH_D3D10:
5346 case RENDERPATH_D3D11:
5347 case RENDERPATH_SOFT:
5350 GL_CullFace(r_refdef.view.cullface_back);
5355 R_RenderView_UpdateViewVectors
5358 static void R_RenderView_UpdateViewVectors(void)
5360 // break apart the view matrix into vectors for various purposes
5361 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5362 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5363 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5364 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5365 // make an inverted copy of the view matrix for tracking sprites
5366 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5369 void R_RenderScene(void);
5370 void R_RenderWaterPlanes(void);
5372 static void R_Water_StartFrame(void)
5375 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5376 r_waterstate_waterplane_t *p;
5378 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5381 switch(vid.renderpath)
5383 case RENDERPATH_GL20:
5384 case RENDERPATH_D3D9:
5385 case RENDERPATH_D3D10:
5386 case RENDERPATH_D3D11:
5387 case RENDERPATH_SOFT:
5388 case RENDERPATH_GLES2:
5390 case RENDERPATH_GL11:
5391 case RENDERPATH_GL13:
5392 case RENDERPATH_GLES1:
5396 // set waterwidth and waterheight to the water resolution that will be
5397 // used (often less than the screen resolution for faster rendering)
5398 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5400 // calculate desired texture sizes
5401 // can't use water if the card does not support the texture size
5402 if (!r_water.integer || r_showsurfaces.integer)
5403 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5404 else if (vid.support.arb_texture_non_power_of_two)
5406 texturewidth = waterwidth;
5407 textureheight = waterheight;
5408 camerawidth = waterwidth;
5409 cameraheight = waterheight;
5413 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5414 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5415 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5416 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5419 // allocate textures as needed
5420 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5422 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5423 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5425 if (p->texture_refraction)
5426 R_FreeTexture(p->texture_refraction);
5427 p->texture_refraction = NULL;
5428 if (p->texture_reflection)
5429 R_FreeTexture(p->texture_reflection);
5430 p->texture_reflection = NULL;
5431 if (p->texture_camera)
5432 R_FreeTexture(p->texture_camera);
5433 p->texture_camera = NULL;
5435 memset(&r_waterstate, 0, sizeof(r_waterstate));
5436 r_waterstate.texturewidth = texturewidth;
5437 r_waterstate.textureheight = textureheight;
5438 r_waterstate.camerawidth = camerawidth;
5439 r_waterstate.cameraheight = cameraheight;
5442 if (r_waterstate.texturewidth)
5444 int scaledwidth, scaledheight;
5446 r_waterstate.enabled = true;
5448 // when doing a reduced render (HDR) we want to use a smaller area
5449 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5450 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5451 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5453 // set up variables that will be used in shader setup
5454 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5455 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5456 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5457 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5460 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5461 r_waterstate.numwaterplanes = 0;
5464 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5466 int triangleindex, planeindex;
5472 r_waterstate_waterplane_t *p;
5473 texture_t *t = R_GetCurrentTexture(surface->texture);
5475 // just use the first triangle with a valid normal for any decisions
5476 VectorClear(normal);
5477 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5479 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5480 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5481 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5482 TriangleNormal(vert[0], vert[1], vert[2], normal);
5483 if (VectorLength2(normal) >= 0.001)
5487 VectorCopy(normal, plane.normal);
5488 VectorNormalize(plane.normal);
5489 plane.dist = DotProduct(vert[0], plane.normal);
5490 PlaneClassify(&plane);
5491 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5493 // skip backfaces (except if nocullface is set)
5494 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5496 VectorNegate(plane.normal, plane.normal);
5498 PlaneClassify(&plane);
5502 // find a matching plane if there is one
5503 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5504 if(p->camera_entity == t->camera_entity)
5505 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5507 if (planeindex >= r_waterstate.maxwaterplanes)
5508 return; // nothing we can do, out of planes
5510 // if this triangle does not fit any known plane rendered this frame, add one
5511 if (planeindex >= r_waterstate.numwaterplanes)
5513 // store the new plane
5514 r_waterstate.numwaterplanes++;
5516 // clear materialflags and pvs
5517 p->materialflags = 0;
5518 p->pvsvalid = false;
5519 p->camera_entity = t->camera_entity;
5520 VectorCopy(surface->mins, p->mins);
5521 VectorCopy(surface->maxs, p->maxs);
5526 p->mins[0] = min(p->mins[0], surface->mins[0]);
5527 p->mins[1] = min(p->mins[1], surface->mins[1]);
5528 p->mins[2] = min(p->mins[2], surface->mins[2]);
5529 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5530 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5531 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5533 // merge this surface's materialflags into the waterplane
5534 p->materialflags |= t->currentmaterialflags;
5535 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5537 // merge this surface's PVS into the waterplane
5538 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5539 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5540 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5542 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5548 static void R_Water_ProcessPlanes(void)
5551 r_refdef_view_t originalview;
5552 r_refdef_view_t myview;
5554 r_waterstate_waterplane_t *p;
5557 originalview = r_refdef.view;
5559 // make sure enough textures are allocated
5560 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5562 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5564 if (!p->texture_refraction)
5565 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);
5566 if (!p->texture_refraction)
5569 else if (p->materialflags & MATERIALFLAG_CAMERA)
5571 if (!p->texture_camera)
5572 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);
5573 if (!p->texture_camera)
5577 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5579 if (!p->texture_reflection)
5580 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);
5581 if (!p->texture_reflection)
5587 r_refdef.view = originalview;
5588 r_refdef.view.showdebug = false;
5589 r_refdef.view.width = r_waterstate.waterwidth;
5590 r_refdef.view.height = r_waterstate.waterheight;
5591 r_refdef.view.useclipplane = true;
5592 myview = r_refdef.view;
5593 r_waterstate.renderingscene = true;
5594 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5596 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5598 r_refdef.view = myview;
5599 if(r_water_scissormode.integer)
5602 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5603 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5606 // render reflected scene and copy into texture
5607 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5608 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5609 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5610 r_refdef.view.clipplane = p->plane;
5612 // reverse the cullface settings for this render
5613 r_refdef.view.cullface_front = GL_FRONT;
5614 r_refdef.view.cullface_back = GL_BACK;
5615 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5617 r_refdef.view.usecustompvs = true;
5619 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5621 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5624 R_ResetViewRendering3D();
5625 R_ClearScreen(r_refdef.fogenabled);
5626 if(r_water_scissormode.integer & 2)
5627 R_View_UpdateWithScissor(myscissor);
5630 if(r_water_scissormode.integer & 1)
5631 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5634 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);
5637 // render the normal view scene and copy into texture
5638 // (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)
5639 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5641 r_refdef.view = myview;
5642 if(r_water_scissormode.integer)
5645 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5646 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5649 r_waterstate.renderingrefraction = true;
5651 r_refdef.view.clipplane = p->plane;
5652 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5653 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5655 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5657 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5658 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5659 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5660 R_RenderView_UpdateViewVectors();
5661 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5663 r_refdef.view.usecustompvs = true;
5664 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);
5668 PlaneClassify(&r_refdef.view.clipplane);
5670 R_ResetViewRendering3D();
5671 R_ClearScreen(r_refdef.fogenabled);
5672 if(r_water_scissormode.integer & 2)
5673 R_View_UpdateWithScissor(myscissor);
5676 if(r_water_scissormode.integer & 1)
5677 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5680 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);
5681 r_waterstate.renderingrefraction = false;
5683 else if (p->materialflags & MATERIALFLAG_CAMERA)
5685 r_refdef.view = myview;
5687 r_refdef.view.clipplane = p->plane;
5688 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5689 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5691 r_refdef.view.width = r_waterstate.camerawidth;
5692 r_refdef.view.height = r_waterstate.cameraheight;
5693 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5694 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5696 if(p->camera_entity)
5698 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5699 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5702 // note: all of the view is used for displaying... so
5703 // there is no use in scissoring
5705 // reverse the cullface settings for this render
5706 r_refdef.view.cullface_front = GL_FRONT;
5707 r_refdef.view.cullface_back = GL_BACK;
5708 // also reverse the view matrix
5709 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
5710 R_RenderView_UpdateViewVectors();
5711 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5713 r_refdef.view.usecustompvs = true;
5714 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);
5717 // camera needs no clipplane
5718 r_refdef.view.useclipplane = false;
5720 PlaneClassify(&r_refdef.view.clipplane);
5722 R_ResetViewRendering3D();
5723 R_ClearScreen(r_refdef.fogenabled);
5727 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);
5728 r_waterstate.renderingrefraction = false;
5732 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5733 r_waterstate.renderingscene = false;
5734 r_refdef.view = originalview;
5735 R_ResetViewRendering3D();
5736 R_ClearScreen(r_refdef.fogenabled);
5740 r_refdef.view = originalview;
5741 r_waterstate.renderingscene = false;
5742 Cvar_SetValueQuick(&r_water, 0);
5743 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5747 void R_Bloom_StartFrame(void)
5749 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5750 int viewwidth, viewheight;
5753 if (r_viewscale_fpsscaling.integer)
5755 double actualframetime;
5756 double targetframetime;
5758 actualframetime = r_refdef.lastdrawscreentime;
5759 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5760 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5761 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5762 if (r_viewscale_fpsscaling_stepsize.value > 0)
5763 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5764 viewscalefpsadjusted += adjust;
5765 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5768 viewscalefpsadjusted = 1.0f;
5770 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5772 switch(vid.renderpath)
5774 case RENDERPATH_GL20:
5775 case RENDERPATH_D3D9:
5776 case RENDERPATH_D3D10:
5777 case RENDERPATH_D3D11:
5778 case RENDERPATH_SOFT:
5779 case RENDERPATH_GLES2:
5781 case RENDERPATH_GL11:
5782 case RENDERPATH_GL13:
5783 case RENDERPATH_GLES1:
5787 // set bloomwidth and bloomheight to the bloom resolution that will be
5788 // used (often less than the screen resolution for faster rendering)
5789 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5790 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5791 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5792 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5793 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5795 // calculate desired texture sizes
5796 if (vid.support.arb_texture_non_power_of_two)
5798 screentexturewidth = vid.width;
5799 screentextureheight = vid.height;
5800 bloomtexturewidth = r_bloomstate.bloomwidth;
5801 bloomtextureheight = r_bloomstate.bloomheight;
5805 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5806 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5807 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5808 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5811 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))
5813 Cvar_SetValueQuick(&r_hdr, 0);
5814 Cvar_SetValueQuick(&r_bloom, 0);
5815 Cvar_SetValueQuick(&r_motionblur, 0);
5816 Cvar_SetValueQuick(&r_damageblur, 0);
5819 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)
5820 screentexturewidth = screentextureheight = 0;
5821 if (!r_hdr.integer && !r_bloom.integer)
5822 bloomtexturewidth = bloomtextureheight = 0;
5824 textype = TEXTYPE_COLORBUFFER;
5825 switch (vid.renderpath)
5827 case RENDERPATH_GL20:
5828 case RENDERPATH_GLES2:
5829 if (vid.support.ext_framebuffer_object)
5831 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5832 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5835 case RENDERPATH_GL11:
5836 case RENDERPATH_GL13:
5837 case RENDERPATH_GLES1:
5838 case RENDERPATH_D3D9:
5839 case RENDERPATH_D3D10:
5840 case RENDERPATH_D3D11:
5841 case RENDERPATH_SOFT:
5845 // allocate textures as needed
5846 if (r_bloomstate.screentexturewidth != screentexturewidth
5847 || r_bloomstate.screentextureheight != screentextureheight
5848 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5849 || r_bloomstate.bloomtextureheight != bloomtextureheight
5850 || r_bloomstate.texturetype != textype
5851 || r_bloomstate.viewfbo != r_viewfbo.integer)
5853 if (r_bloomstate.texture_bloom)
5854 R_FreeTexture(r_bloomstate.texture_bloom);
5855 r_bloomstate.texture_bloom = NULL;
5856 if (r_bloomstate.texture_screen)
5857 R_FreeTexture(r_bloomstate.texture_screen);
5858 r_bloomstate.texture_screen = NULL;
5859 if (r_bloomstate.fbo_framebuffer)
5860 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5861 r_bloomstate.fbo_framebuffer = 0;
5862 if (r_bloomstate.texture_framebuffercolor)
5863 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5864 r_bloomstate.texture_framebuffercolor = NULL;
5865 if (r_bloomstate.texture_framebufferdepth)
5866 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5867 r_bloomstate.texture_framebufferdepth = NULL;
5868 r_bloomstate.screentexturewidth = screentexturewidth;
5869 r_bloomstate.screentextureheight = screentextureheight;
5870 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5871 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);
5872 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5874 // FIXME: choose depth bits based on a cvar
5875 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5876 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);
5877 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5878 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5879 // render depth into one texture and normalmap into the other
5883 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5884 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5885 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5886 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5887 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5890 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5891 r_bloomstate.bloomtextureheight = bloomtextureheight;
5892 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5893 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);
5894 r_bloomstate.viewfbo = r_viewfbo.integer;
5895 r_bloomstate.texturetype = textype;
5898 // when doing a reduced render (HDR) we want to use a smaller area
5899 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5900 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5901 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5902 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5903 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5905 // set up a texcoord array for the full resolution screen image
5906 // (we have to keep this around to copy back during final render)
5907 r_bloomstate.screentexcoord2f[0] = 0;
5908 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5909 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5910 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5911 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5912 r_bloomstate.screentexcoord2f[5] = 0;
5913 r_bloomstate.screentexcoord2f[6] = 0;
5914 r_bloomstate.screentexcoord2f[7] = 0;
5916 // set up a texcoord array for the reduced resolution bloom image
5917 // (which will be additive blended over the screen image)
5918 r_bloomstate.bloomtexcoord2f[0] = 0;
5919 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5920 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5921 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5922 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5923 r_bloomstate.bloomtexcoord2f[5] = 0;
5924 r_bloomstate.bloomtexcoord2f[6] = 0;
5925 r_bloomstate.bloomtexcoord2f[7] = 0;
5927 switch(vid.renderpath)
5929 case RENDERPATH_GL11:
5930 case RENDERPATH_GL13:
5931 case RENDERPATH_GL20:
5932 case RENDERPATH_SOFT:
5933 case RENDERPATH_GLES1:
5934 case RENDERPATH_GLES2:
5936 case RENDERPATH_D3D9:
5937 case RENDERPATH_D3D10:
5938 case RENDERPATH_D3D11:
5941 for (i = 0;i < 4;i++)
5943 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5944 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5945 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5946 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5952 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5954 r_bloomstate.enabled = true;
5955 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5958 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);
5960 if (r_bloomstate.fbo_framebuffer)
5961 r_refdef.view.clear = true;
5964 void R_Bloom_CopyBloomTexture(float colorscale)
5966 r_refdef.stats.bloom++;
5968 // scale down screen texture to the bloom texture size
5970 R_Mesh_SetMainRenderTargets();
5971 R_SetViewport(&r_bloomstate.viewport);
5972 GL_BlendFunc(GL_ONE, GL_ZERO);
5973 GL_Color(colorscale, colorscale, colorscale, 1);
5974 // 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...
5975 switch(vid.renderpath)
5977 case RENDERPATH_GL11:
5978 case RENDERPATH_GL13:
5979 case RENDERPATH_GL20:
5980 case RENDERPATH_GLES1:
5981 case RENDERPATH_GLES2:
5982 case RENDERPATH_SOFT:
5983 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5985 case RENDERPATH_D3D9:
5986 case RENDERPATH_D3D10:
5987 case RENDERPATH_D3D11:
5988 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5991 // TODO: do boxfilter scale-down in shader?
5992 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5993 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5994 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5996 // we now have a bloom image in the framebuffer
5997 // copy it into the bloom image texture for later processing
5998 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);
5999 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6002 void R_Bloom_CopyHDRTexture(void)
6004 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);
6005 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6008 void R_Bloom_MakeTexture(void)
6011 float xoffset, yoffset, r, brighten;
6013 r_refdef.stats.bloom++;
6015 R_ResetViewRendering2D();
6017 // we have a bloom image in the framebuffer
6019 R_SetViewport(&r_bloomstate.viewport);
6021 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6024 r = bound(0, r_bloom_colorexponent.value / x, 1);
6025 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6027 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6028 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6029 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6030 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6032 // copy the vertically blurred bloom view to a texture
6033 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);
6034 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6037 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6038 brighten = r_bloom_brighten.value;
6039 if (r_bloomstate.hdr)
6040 brighten *= r_hdr_range.value;
6041 brighten = sqrt(brighten);
6043 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6044 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6046 for (dir = 0;dir < 2;dir++)
6048 // blend on at multiple vertical offsets to achieve a vertical blur
6049 // TODO: do offset blends using GLSL
6050 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6051 GL_BlendFunc(GL_ONE, GL_ZERO);
6052 for (x = -range;x <= range;x++)
6054 if (!dir){xoffset = 0;yoffset = x;}
6055 else {xoffset = x;yoffset = 0;}
6056 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6057 yoffset /= (float)r_bloomstate.bloomtextureheight;
6058 // compute a texcoord array with the specified x and y offset
6059 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6060 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6061 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6062 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6063 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6064 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6065 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6066 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6067 // this r value looks like a 'dot' particle, fading sharply to
6068 // black at the edges
6069 // (probably not realistic but looks good enough)
6070 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6071 //r = brighten/(range*2+1);
6072 r = brighten / (range * 2 + 1);
6074 r *= (1 - x*x/(float)(range*range));
6075 GL_Color(r, r, r, 1);
6076 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6077 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6078 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6079 GL_BlendFunc(GL_ONE, GL_ONE);
6082 // copy the vertically blurred bloom view to a texture
6083 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);
6084 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6088 void R_HDR_RenderBloomTexture(void)
6090 int oldwidth, oldheight;
6091 float oldcolorscale;
6092 qboolean oldwaterstate;
6094 oldwaterstate = r_waterstate.enabled;
6095 oldcolorscale = r_refdef.view.colorscale;
6096 oldwidth = r_refdef.view.width;
6097 oldheight = r_refdef.view.height;
6098 r_refdef.view.width = r_bloomstate.bloomwidth;
6099 r_refdef.view.height = r_bloomstate.bloomheight;
6101 if(r_hdr.integer < 2)
6102 r_waterstate.enabled = false;
6104 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6105 // TODO: add exposure compensation features
6106 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6108 r_refdef.view.showdebug = false;
6109 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6111 R_ResetViewRendering3D();
6113 R_ClearScreen(r_refdef.fogenabled);
6114 if (r_timereport_active)
6115 R_TimeReport("HDRclear");
6118 if (r_timereport_active)
6119 R_TimeReport("visibility");
6121 // only do secondary renders with HDR if r_hdr is 2 or higher
6122 r_waterstate.numwaterplanes = 0;
6123 if (r_waterstate.enabled)
6124 R_RenderWaterPlanes();
6126 r_refdef.view.showdebug = true;
6128 r_waterstate.numwaterplanes = 0;
6130 R_ResetViewRendering2D();
6132 R_Bloom_CopyHDRTexture();
6133 R_Bloom_MakeTexture();
6135 // restore the view settings
6136 r_waterstate.enabled = oldwaterstate;
6137 r_refdef.view.width = oldwidth;
6138 r_refdef.view.height = oldheight;
6139 r_refdef.view.colorscale = oldcolorscale;
6141 R_ResetViewRendering3D();
6143 R_ClearScreen(r_refdef.fogenabled);
6144 if (r_timereport_active)
6145 R_TimeReport("viewclear");
6148 static void R_BlendView(void)
6150 unsigned int permutation;
6151 float uservecs[4][4];
6153 switch (vid.renderpath)
6155 case RENDERPATH_GL20:
6156 case RENDERPATH_D3D9:
6157 case RENDERPATH_D3D10:
6158 case RENDERPATH_D3D11:
6159 case RENDERPATH_SOFT:
6160 case RENDERPATH_GLES2:
6162 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6163 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6164 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6165 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6166 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6168 if (r_bloomstate.texture_screen)
6170 // make sure the buffer is available
6171 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6173 R_ResetViewRendering2D();
6174 R_Mesh_SetMainRenderTargets();
6176 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6178 // declare variables
6180 static float avgspeed;
6182 speed = VectorLength(cl.movement_velocity);
6184 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6185 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6187 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6188 speed = bound(0, speed, 1);
6189 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6191 // calculate values into a standard alpha
6192 cl.motionbluralpha = 1 - exp(-
6194 (r_motionblur.value * speed / 80)
6196 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6199 max(0.0001, cl.time - cl.oldtime) // fps independent
6202 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6203 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6205 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6207 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6208 GL_Color(1, 1, 1, cl.motionbluralpha);
6209 switch(vid.renderpath)
6211 case RENDERPATH_GL11:
6212 case RENDERPATH_GL13:
6213 case RENDERPATH_GL20:
6214 case RENDERPATH_GLES1:
6215 case RENDERPATH_GLES2:
6216 case RENDERPATH_SOFT:
6217 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6219 case RENDERPATH_D3D9:
6220 case RENDERPATH_D3D10:
6221 case RENDERPATH_D3D11:
6222 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6225 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6226 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6227 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6231 // copy view into the screen texture
6232 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);
6233 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6235 else if (!r_bloomstate.texture_bloom)
6237 // we may still have to do view tint...
6238 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6240 // apply a color tint to the whole view
6241 R_ResetViewRendering2D();
6242 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6243 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6244 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6245 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6246 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6248 break; // no screen processing, no bloom, skip it
6251 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6253 // render simple bloom effect
6254 // copy the screen and shrink it and darken it for the bloom process
6255 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6256 // make the bloom texture
6257 R_Bloom_MakeTexture();
6260 #if _MSC_VER >= 1400
6261 #define sscanf sscanf_s
6263 memset(uservecs, 0, sizeof(uservecs));
6264 if (r_glsl_postprocess_uservec1_enable.integer)
6265 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6266 if (r_glsl_postprocess_uservec2_enable.integer)
6267 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6268 if (r_glsl_postprocess_uservec3_enable.integer)
6269 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6270 if (r_glsl_postprocess_uservec4_enable.integer)
6271 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6273 R_ResetViewRendering2D();
6274 GL_Color(1, 1, 1, 1);
6275 GL_BlendFunc(GL_ONE, GL_ZERO);
6277 switch(vid.renderpath)
6279 case RENDERPATH_GL20:
6280 case RENDERPATH_GLES2:
6281 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6282 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6283 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6284 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6285 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6286 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]);
6287 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6288 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]);
6289 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]);
6290 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]);
6291 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]);
6292 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6293 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6294 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);
6296 case RENDERPATH_D3D9:
6298 // 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...
6299 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6300 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6301 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6302 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6303 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6304 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6305 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6306 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6307 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6308 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6309 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6310 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6311 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6312 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6315 case RENDERPATH_D3D10:
6316 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6318 case RENDERPATH_D3D11:
6319 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6321 case RENDERPATH_SOFT:
6322 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6323 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6324 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6325 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6326 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6327 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6328 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6329 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6330 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6331 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6332 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6333 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6334 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6335 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6340 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6341 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6343 case RENDERPATH_GL11:
6344 case RENDERPATH_GL13:
6345 case RENDERPATH_GLES1:
6346 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6348 // apply a color tint to the whole view
6349 R_ResetViewRendering2D();
6350 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6351 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6352 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6353 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6354 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6360 matrix4x4_t r_waterscrollmatrix;
6362 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6364 if (r_refdef.fog_density)
6366 r_refdef.fogcolor[0] = r_refdef.fog_red;
6367 r_refdef.fogcolor[1] = r_refdef.fog_green;
6368 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6370 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6371 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6372 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6373 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6377 VectorCopy(r_refdef.fogcolor, fogvec);
6378 // color.rgb *= ContrastBoost * SceneBrightness;
6379 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6380 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6381 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6382 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6387 void R_UpdateVariables(void)
6391 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6393 r_refdef.farclip = r_farclip_base.value;
6394 if (r_refdef.scene.worldmodel)
6395 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6396 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6398 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6399 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6400 r_refdef.polygonfactor = 0;
6401 r_refdef.polygonoffset = 0;
6402 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6403 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6405 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6406 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6407 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6408 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6409 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6410 if (FAKELIGHT_ENABLED)
6412 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6414 if (r_showsurfaces.integer)
6416 r_refdef.scene.rtworld = false;
6417 r_refdef.scene.rtworldshadows = false;
6418 r_refdef.scene.rtdlight = false;
6419 r_refdef.scene.rtdlightshadows = false;
6420 r_refdef.lightmapintensity = 0;
6423 if (gamemode == GAME_NEHAHRA)
6425 if (gl_fogenable.integer)
6427 r_refdef.oldgl_fogenable = true;
6428 r_refdef.fog_density = gl_fogdensity.value;
6429 r_refdef.fog_red = gl_fogred.value;
6430 r_refdef.fog_green = gl_foggreen.value;
6431 r_refdef.fog_blue = gl_fogblue.value;
6432 r_refdef.fog_alpha = 1;
6433 r_refdef.fog_start = 0;
6434 r_refdef.fog_end = gl_skyclip.value;
6435 r_refdef.fog_height = 1<<30;
6436 r_refdef.fog_fadedepth = 128;
6438 else if (r_refdef.oldgl_fogenable)
6440 r_refdef.oldgl_fogenable = false;
6441 r_refdef.fog_density = 0;
6442 r_refdef.fog_red = 0;
6443 r_refdef.fog_green = 0;
6444 r_refdef.fog_blue = 0;
6445 r_refdef.fog_alpha = 0;
6446 r_refdef.fog_start = 0;
6447 r_refdef.fog_end = 0;
6448 r_refdef.fog_height = 1<<30;
6449 r_refdef.fog_fadedepth = 128;
6453 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6454 r_refdef.fog_start = max(0, r_refdef.fog_start);
6455 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6457 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6459 if (r_refdef.fog_density && r_drawfog.integer)
6461 r_refdef.fogenabled = true;
6462 // this is the point where the fog reaches 0.9986 alpha, which we
6463 // consider a good enough cutoff point for the texture
6464 // (0.9986 * 256 == 255.6)
6465 if (r_fog_exp2.integer)
6466 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6468 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6469 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6470 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6471 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6472 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6473 R_BuildFogHeightTexture();
6474 // fog color was already set
6475 // update the fog texture
6476 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)
6477 R_BuildFogTexture();
6478 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6479 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6482 r_refdef.fogenabled = false;
6484 switch(vid.renderpath)
6486 case RENDERPATH_GL20:
6487 case RENDERPATH_D3D9:
6488 case RENDERPATH_D3D10:
6489 case RENDERPATH_D3D11:
6490 case RENDERPATH_SOFT:
6491 case RENDERPATH_GLES2:
6492 if(v_glslgamma.integer && !vid_gammatables_trivial)
6494 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6496 // build GLSL gamma texture
6497 #define RAMPWIDTH 256
6498 unsigned short ramp[RAMPWIDTH * 3];
6499 unsigned char rampbgr[RAMPWIDTH][4];
6502 r_texture_gammaramps_serial = vid_gammatables_serial;
6504 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6505 for(i = 0; i < RAMPWIDTH; ++i)
6507 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6508 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6509 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6512 if (r_texture_gammaramps)
6514 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6518 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6524 // remove GLSL gamma texture
6527 case RENDERPATH_GL11:
6528 case RENDERPATH_GL13:
6529 case RENDERPATH_GLES1:
6534 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6535 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6541 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6542 if( scenetype != r_currentscenetype ) {
6543 // store the old scenetype
6544 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6545 r_currentscenetype = scenetype;
6546 // move in the new scene
6547 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6556 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6558 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6559 if( scenetype == r_currentscenetype ) {
6560 return &r_refdef.scene;
6562 return &r_scenes_store[ scenetype ];
6571 int dpsoftrast_test;
6572 void R_RenderView(void)
6574 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6576 dpsoftrast_test = r_test.integer;
6578 if (r_timereport_active)
6579 R_TimeReport("start");
6580 r_textureframe++; // used only by R_GetCurrentTexture
6581 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6583 if(R_CompileShader_CheckStaticParms())
6586 if (!r_drawentities.integer)
6587 r_refdef.scene.numentities = 0;
6589 R_AnimCache_ClearCache();
6590 R_FrameData_NewFrame();
6592 /* adjust for stereo display */
6593 if(R_Stereo_Active())
6595 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);
6596 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6599 if (r_refdef.view.isoverlay)
6601 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6602 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6603 R_TimeReport("depthclear");
6605 r_refdef.view.showdebug = false;
6607 r_waterstate.enabled = false;
6608 r_waterstate.numwaterplanes = 0;
6612 r_refdef.view.matrix = originalmatrix;
6618 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6620 r_refdef.view.matrix = originalmatrix;
6621 return; //Host_Error ("R_RenderView: NULL worldmodel");
6624 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6626 R_RenderView_UpdateViewVectors();
6628 R_Shadow_UpdateWorldLightSelection();
6630 R_Bloom_StartFrame();
6631 R_Water_StartFrame();
6634 if (r_timereport_active)
6635 R_TimeReport("viewsetup");
6637 R_ResetViewRendering3D();
6639 if (r_refdef.view.clear || r_refdef.fogenabled)
6641 R_ClearScreen(r_refdef.fogenabled);
6642 if (r_timereport_active)
6643 R_TimeReport("viewclear");
6645 r_refdef.view.clear = true;
6647 // this produces a bloom texture to be used in R_BlendView() later
6648 if (r_bloomstate.hdr)
6650 R_HDR_RenderBloomTexture();
6651 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6652 r_textureframe++; // used only by R_GetCurrentTexture
6655 r_refdef.view.showdebug = true;
6658 if (r_timereport_active)
6659 R_TimeReport("visibility");
6661 r_waterstate.numwaterplanes = 0;
6662 if (r_waterstate.enabled)
6663 R_RenderWaterPlanes();
6666 r_waterstate.numwaterplanes = 0;
6669 if (r_timereport_active)
6670 R_TimeReport("blendview");
6672 GL_Scissor(0, 0, vid.width, vid.height);
6673 GL_ScissorTest(false);
6675 r_refdef.view.matrix = originalmatrix;
6680 void R_RenderWaterPlanes(void)
6682 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6684 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6685 if (r_timereport_active)
6686 R_TimeReport("waterworld");
6689 // don't let sound skip if going slow
6690 if (r_refdef.scene.extraupdate)
6693 R_DrawModelsAddWaterPlanes();
6694 if (r_timereport_active)
6695 R_TimeReport("watermodels");
6697 if (r_waterstate.numwaterplanes)
6699 R_Water_ProcessPlanes();
6700 if (r_timereport_active)
6701 R_TimeReport("waterscenes");
6705 extern void R_DrawLightningBeams (void);
6706 extern void VM_CL_AddPolygonsToMeshQueue (void);
6707 extern void R_DrawPortals (void);
6708 extern cvar_t cl_locs_show;
6709 static void R_DrawLocs(void);
6710 static void R_DrawEntityBBoxes(void);
6711 static void R_DrawModelDecals(void);
6712 extern void R_DrawModelShadows(void);
6713 extern void R_DrawModelShadowMaps(void);
6714 extern cvar_t cl_decals_newsystem;
6715 extern qboolean r_shadow_usingdeferredprepass;
6716 void R_RenderScene(void)
6718 qboolean shadowmapping = false;
6720 if (r_timereport_active)
6721 R_TimeReport("beginscene");
6723 r_refdef.stats.renders++;
6727 // don't let sound skip if going slow
6728 if (r_refdef.scene.extraupdate)
6731 R_MeshQueue_BeginScene();
6735 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);
6737 if (r_timereport_active)
6738 R_TimeReport("skystartframe");
6740 if (cl.csqc_vidvars.drawworld)
6742 // don't let sound skip if going slow
6743 if (r_refdef.scene.extraupdate)
6746 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6748 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6749 if (r_timereport_active)
6750 R_TimeReport("worldsky");
6753 if (R_DrawBrushModelsSky() && r_timereport_active)
6754 R_TimeReport("bmodelsky");
6756 if (skyrendermasked && skyrenderlater)
6758 // we have to force off the water clipping plane while rendering sky
6762 if (r_timereport_active)
6763 R_TimeReport("sky");
6767 R_AnimCache_CacheVisibleEntities();
6768 if (r_timereport_active)
6769 R_TimeReport("animation");
6771 R_Shadow_PrepareLights();
6772 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6773 R_Shadow_PrepareModelShadows();
6774 if (r_timereport_active)
6775 R_TimeReport("preparelights");
6777 if (R_Shadow_ShadowMappingEnabled())
6778 shadowmapping = true;
6780 if (r_shadow_usingdeferredprepass)
6781 R_Shadow_DrawPrepass();
6783 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6785 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6786 if (r_timereport_active)
6787 R_TimeReport("worlddepth");
6789 if (r_depthfirst.integer >= 2)
6791 R_DrawModelsDepth();
6792 if (r_timereport_active)
6793 R_TimeReport("modeldepth");
6796 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6798 R_DrawModelShadowMaps();
6799 R_ResetViewRendering3D();
6800 // don't let sound skip if going slow
6801 if (r_refdef.scene.extraupdate)
6805 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6807 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6808 if (r_timereport_active)
6809 R_TimeReport("world");
6812 // don't let sound skip if going slow
6813 if (r_refdef.scene.extraupdate)
6817 if (r_timereport_active)
6818 R_TimeReport("models");
6820 // don't let sound skip if going slow
6821 if (r_refdef.scene.extraupdate)
6824 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6826 R_DrawModelShadows();
6827 R_ResetViewRendering3D();
6828 // don't let sound skip if going slow
6829 if (r_refdef.scene.extraupdate)
6833 if (!r_shadow_usingdeferredprepass)
6835 R_Shadow_DrawLights();
6836 if (r_timereport_active)
6837 R_TimeReport("rtlights");
6840 // don't let sound skip if going slow
6841 if (r_refdef.scene.extraupdate)
6844 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6846 R_DrawModelShadows();
6847 R_ResetViewRendering3D();
6848 // don't let sound skip if going slow
6849 if (r_refdef.scene.extraupdate)
6853 if (cl.csqc_vidvars.drawworld)
6855 if (cl_decals_newsystem.integer)
6857 R_DrawModelDecals();
6858 if (r_timereport_active)
6859 R_TimeReport("modeldecals");
6864 if (r_timereport_active)
6865 R_TimeReport("decals");
6869 if (r_timereport_active)
6870 R_TimeReport("particles");
6873 if (r_timereport_active)
6874 R_TimeReport("explosions");
6876 R_DrawLightningBeams();
6877 if (r_timereport_active)
6878 R_TimeReport("lightning");
6881 VM_CL_AddPolygonsToMeshQueue();
6883 if (r_refdef.view.showdebug)
6885 if (cl_locs_show.integer)
6888 if (r_timereport_active)
6889 R_TimeReport("showlocs");
6892 if (r_drawportals.integer)
6895 if (r_timereport_active)
6896 R_TimeReport("portals");
6899 if (r_showbboxes.value > 0)
6901 R_DrawEntityBBoxes();
6902 if (r_timereport_active)
6903 R_TimeReport("bboxes");
6907 if (r_transparent.integer)
6909 R_MeshQueue_RenderTransparent();
6910 if (r_timereport_active)
6911 R_TimeReport("drawtrans");
6914 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))
6916 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6917 if (r_timereport_active)
6918 R_TimeReport("worlddebug");
6919 R_DrawModelsDebug();
6920 if (r_timereport_active)
6921 R_TimeReport("modeldebug");
6924 if (cl.csqc_vidvars.drawworld)
6926 R_Shadow_DrawCoronas();
6927 if (r_timereport_active)
6928 R_TimeReport("coronas");
6933 GL_DepthTest(false);
6934 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6935 GL_Color(1, 1, 1, 1);
6936 qglBegin(GL_POLYGON);
6937 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6938 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6939 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6940 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6942 qglBegin(GL_POLYGON);
6943 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]);
6944 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]);
6945 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]);
6946 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]);
6948 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6952 // don't let sound skip if going slow
6953 if (r_refdef.scene.extraupdate)
6956 R_ResetViewRendering2D();
6959 static const unsigned short bboxelements[36] =
6969 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6972 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6974 RSurf_ActiveWorldEntity();
6976 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6977 GL_DepthMask(false);
6978 GL_DepthRange(0, 1);
6979 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6980 // R_Mesh_ResetTextureState();
6982 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6983 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6984 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6985 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6986 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6987 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6988 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6989 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6990 R_FillColors(color4f, 8, cr, cg, cb, ca);
6991 if (r_refdef.fogenabled)
6993 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6995 f1 = RSurf_FogVertex(v);
6997 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6998 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6999 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7002 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7003 R_Mesh_ResetTextureState();
7004 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7005 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7008 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7012 prvm_edict_t *edict;
7013 prvm_prog_t *prog_save = prog;
7015 // this function draws bounding boxes of server entities
7019 GL_CullFace(GL_NONE);
7020 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7024 for (i = 0;i < numsurfaces;i++)
7026 edict = PRVM_EDICT_NUM(surfacelist[i]);
7027 switch ((int)edict->fields.server->solid)
7029 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7030 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7031 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7032 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7033 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7034 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7036 color[3] *= r_showbboxes.value;
7037 color[3] = bound(0, color[3], 1);
7038 GL_DepthTest(!r_showdisabledepthtest.integer);
7039 GL_CullFace(r_refdef.view.cullface_front);
7040 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7046 static void R_DrawEntityBBoxes(void)
7049 prvm_edict_t *edict;
7051 prvm_prog_t *prog_save = prog;
7053 // this function draws bounding boxes of server entities
7059 for (i = 0;i < prog->num_edicts;i++)
7061 edict = PRVM_EDICT_NUM(i);
7062 if (edict->priv.server->free)
7064 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7065 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7067 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7069 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7070 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7076 static const int nomodelelement3i[24] =
7088 static const unsigned short nomodelelement3s[24] =
7100 static const float nomodelvertex3f[6*3] =
7110 static const float nomodelcolor4f[6*4] =
7112 0.0f, 0.0f, 0.5f, 1.0f,
7113 0.0f, 0.0f, 0.5f, 1.0f,
7114 0.0f, 0.5f, 0.0f, 1.0f,
7115 0.0f, 0.5f, 0.0f, 1.0f,
7116 0.5f, 0.0f, 0.0f, 1.0f,
7117 0.5f, 0.0f, 0.0f, 1.0f
7120 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7126 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);
7128 // this is only called once per entity so numsurfaces is always 1, and
7129 // surfacelist is always {0}, so this code does not handle batches
7131 if (rsurface.ent_flags & RENDER_ADDITIVE)
7133 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7134 GL_DepthMask(false);
7136 else if (rsurface.colormod[3] < 1)
7138 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7139 GL_DepthMask(false);
7143 GL_BlendFunc(GL_ONE, GL_ZERO);
7146 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7147 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7148 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7149 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7150 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7151 for (i = 0, c = color4f;i < 6;i++, c += 4)
7153 c[0] *= rsurface.colormod[0];
7154 c[1] *= rsurface.colormod[1];
7155 c[2] *= rsurface.colormod[2];
7156 c[3] *= rsurface.colormod[3];
7158 if (r_refdef.fogenabled)
7160 for (i = 0, c = color4f;i < 6;i++, c += 4)
7162 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7164 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7165 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7166 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7169 // R_Mesh_ResetTextureState();
7170 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7171 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7172 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7175 void R_DrawNoModel(entity_render_t *ent)
7178 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7179 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7180 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7182 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7185 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7187 vec3_t right1, right2, diff, normal;
7189 VectorSubtract (org2, org1, normal);
7191 // calculate 'right' vector for start
7192 VectorSubtract (r_refdef.view.origin, org1, diff);
7193 CrossProduct (normal, diff, right1);
7194 VectorNormalize (right1);
7196 // calculate 'right' vector for end
7197 VectorSubtract (r_refdef.view.origin, org2, diff);
7198 CrossProduct (normal, diff, right2);
7199 VectorNormalize (right2);
7201 vert[ 0] = org1[0] + width * right1[0];
7202 vert[ 1] = org1[1] + width * right1[1];
7203 vert[ 2] = org1[2] + width * right1[2];
7204 vert[ 3] = org1[0] - width * right1[0];
7205 vert[ 4] = org1[1] - width * right1[1];
7206 vert[ 5] = org1[2] - width * right1[2];
7207 vert[ 6] = org2[0] - width * right2[0];
7208 vert[ 7] = org2[1] - width * right2[1];
7209 vert[ 8] = org2[2] - width * right2[2];
7210 vert[ 9] = org2[0] + width * right2[0];
7211 vert[10] = org2[1] + width * right2[1];
7212 vert[11] = org2[2] + width * right2[2];
7215 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)
7217 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7218 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7219 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7220 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7221 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7222 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7223 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7224 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7225 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7226 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7227 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7228 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7231 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7236 VectorSet(v, x, y, z);
7237 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7238 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7240 if (i == mesh->numvertices)
7242 if (mesh->numvertices < mesh->maxvertices)
7244 VectorCopy(v, vertex3f);
7245 mesh->numvertices++;
7247 return mesh->numvertices;
7253 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7257 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7258 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7259 e = mesh->element3i + mesh->numtriangles * 3;
7260 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7262 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7263 if (mesh->numtriangles < mesh->maxtriangles)
7268 mesh->numtriangles++;
7270 element[1] = element[2];
7274 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7278 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7279 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7280 e = mesh->element3i + mesh->numtriangles * 3;
7281 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7283 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7284 if (mesh->numtriangles < mesh->maxtriangles)
7289 mesh->numtriangles++;
7291 element[1] = element[2];
7295 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7296 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7298 int planenum, planenum2;
7301 mplane_t *plane, *plane2;
7303 double temppoints[2][256*3];
7304 // figure out how large a bounding box we need to properly compute this brush
7306 for (w = 0;w < numplanes;w++)
7307 maxdist = max(maxdist, fabs(planes[w].dist));
7308 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7309 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7310 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7314 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7315 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7317 if (planenum2 == planenum)
7319 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);
7322 if (tempnumpoints < 3)
7324 // generate elements forming a triangle fan for this polygon
7325 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7329 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)
7331 texturelayer_t *layer;
7332 layer = t->currentlayers + t->currentnumlayers++;
7334 layer->depthmask = depthmask;
7335 layer->blendfunc1 = blendfunc1;
7336 layer->blendfunc2 = blendfunc2;
7337 layer->texture = texture;
7338 layer->texmatrix = *matrix;
7339 layer->color[0] = r;
7340 layer->color[1] = g;
7341 layer->color[2] = b;
7342 layer->color[3] = a;
7345 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7347 if(parms[0] == 0 && parms[1] == 0)
7349 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7350 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7355 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7358 index = parms[2] + r_refdef.scene.time * parms[3];
7359 index -= floor(index);
7360 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7363 case Q3WAVEFUNC_NONE:
7364 case Q3WAVEFUNC_NOISE:
7365 case Q3WAVEFUNC_COUNT:
7368 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7369 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7370 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7371 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7372 case Q3WAVEFUNC_TRIANGLE:
7374 f = index - floor(index);
7385 f = parms[0] + parms[1] * f;
7386 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7387 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7391 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7396 matrix4x4_t matrix, temp;
7397 switch(tcmod->tcmod)
7401 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7402 matrix = r_waterscrollmatrix;
7404 matrix = identitymatrix;
7406 case Q3TCMOD_ENTITYTRANSLATE:
7407 // this is used in Q3 to allow the gamecode to control texcoord
7408 // scrolling on the entity, which is not supported in darkplaces yet.
7409 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7411 case Q3TCMOD_ROTATE:
7412 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7413 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7414 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7417 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7419 case Q3TCMOD_SCROLL:
7420 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7422 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7423 w = (int) tcmod->parms[0];
7424 h = (int) tcmod->parms[1];
7425 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7427 idx = (int) floor(f * w * h);
7428 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7430 case Q3TCMOD_STRETCH:
7431 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7432 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7434 case Q3TCMOD_TRANSFORM:
7435 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7436 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7437 VectorSet(tcmat + 6, 0 , 0 , 1);
7438 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7439 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7441 case Q3TCMOD_TURBULENT:
7442 // this is handled in the RSurf_PrepareVertices function
7443 matrix = identitymatrix;
7447 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7450 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7452 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7453 char name[MAX_QPATH];
7454 skinframe_t *skinframe;
7455 unsigned char pixels[296*194];
7456 strlcpy(cache->name, skinname, sizeof(cache->name));
7457 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7458 if (developer_loading.integer)
7459 Con_Printf("loading %s\n", name);
7460 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7461 if (!skinframe || !skinframe->base)
7464 fs_offset_t filesize;
7466 f = FS_LoadFile(name, tempmempool, true, &filesize);
7469 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7470 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7474 cache->skinframe = skinframe;
7477 texture_t *R_GetCurrentTexture(texture_t *t)
7480 const entity_render_t *ent = rsurface.entity;
7481 dp_model_t *model = ent->model;
7482 q3shaderinfo_layer_tcmod_t *tcmod;
7484 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7485 return t->currentframe;
7486 t->update_lastrenderframe = r_textureframe;
7487 t->update_lastrenderentity = (void *)ent;
7489 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7490 t->camera_entity = ent->entitynumber;
7492 t->camera_entity = 0;
7494 // switch to an alternate material if this is a q1bsp animated material
7496 texture_t *texture = t;
7497 int s = rsurface.ent_skinnum;
7498 if ((unsigned int)s >= (unsigned int)model->numskins)
7500 if (model->skinscenes)
7502 if (model->skinscenes[s].framecount > 1)
7503 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7505 s = model->skinscenes[s].firstframe;
7508 t = t + s * model->num_surfaces;
7511 // use an alternate animation if the entity's frame is not 0,
7512 // and only if the texture has an alternate animation
7513 if (rsurface.ent_alttextures && t->anim_total[1])
7514 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7516 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7518 texture->currentframe = t;
7521 // update currentskinframe to be a qw skin or animation frame
7522 if (rsurface.ent_qwskin >= 0)
7524 i = rsurface.ent_qwskin;
7525 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7527 r_qwskincache_size = cl.maxclients;
7529 Mem_Free(r_qwskincache);
7530 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7532 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7533 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7534 t->currentskinframe = r_qwskincache[i].skinframe;
7535 if (t->currentskinframe == NULL)
7536 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7538 else if (t->numskinframes >= 2)
7539 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7540 if (t->backgroundnumskinframes >= 2)
7541 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7543 t->currentmaterialflags = t->basematerialflags;
7544 t->currentalpha = rsurface.colormod[3];
7545 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7546 t->currentalpha *= r_wateralpha.value;
7547 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7548 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7549 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7550 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7551 if (!(rsurface.ent_flags & RENDER_LIGHT))
7552 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7553 else if (FAKELIGHT_ENABLED)
7555 // no modellight if using fakelight for the map
7557 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7559 // pick a model lighting mode
7560 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7561 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7563 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7565 if (rsurface.ent_flags & RENDER_ADDITIVE)
7566 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7567 else if (t->currentalpha < 1)
7568 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7569 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7570 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7571 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7572 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7573 if (t->backgroundnumskinframes)
7574 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7575 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7577 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7578 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7581 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7582 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7583 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7585 // there is no tcmod
7586 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7588 t->currenttexmatrix = r_waterscrollmatrix;
7589 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7591 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7593 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7594 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7597 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7598 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7599 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7600 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7602 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7603 if (t->currentskinframe->qpixels)
7604 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7605 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7606 if (!t->basetexture)
7607 t->basetexture = r_texture_notexture;
7608 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7609 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7610 t->nmaptexture = t->currentskinframe->nmap;
7611 if (!t->nmaptexture)
7612 t->nmaptexture = r_texture_blanknormalmap;
7613 t->glosstexture = r_texture_black;
7614 t->glowtexture = t->currentskinframe->glow;
7615 t->fogtexture = t->currentskinframe->fog;
7616 t->reflectmasktexture = t->currentskinframe->reflect;
7617 if (t->backgroundnumskinframes)
7619 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7620 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7621 t->backgroundglosstexture = r_texture_black;
7622 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7623 if (!t->backgroundnmaptexture)
7624 t->backgroundnmaptexture = r_texture_blanknormalmap;
7628 t->backgroundbasetexture = r_texture_white;
7629 t->backgroundnmaptexture = r_texture_blanknormalmap;
7630 t->backgroundglosstexture = r_texture_black;
7631 t->backgroundglowtexture = NULL;
7633 t->specularpower = r_shadow_glossexponent.value;
7634 // TODO: store reference values for these in the texture?
7635 t->specularscale = 0;
7636 if (r_shadow_gloss.integer > 0)
7638 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7640 if (r_shadow_glossintensity.value > 0)
7642 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7643 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7644 t->specularscale = r_shadow_glossintensity.value;
7647 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7649 t->glosstexture = r_texture_white;
7650 t->backgroundglosstexture = r_texture_white;
7651 t->specularscale = r_shadow_gloss2intensity.value;
7652 t->specularpower = r_shadow_gloss2exponent.value;
7655 t->specularscale *= t->specularscalemod;
7656 t->specularpower *= t->specularpowermod;
7658 // lightmaps mode looks bad with dlights using actual texturing, so turn
7659 // off the colormap and glossmap, but leave the normalmap on as it still
7660 // accurately represents the shading involved
7661 if (gl_lightmaps.integer)
7663 t->basetexture = r_texture_grey128;
7664 t->pantstexture = r_texture_black;
7665 t->shirttexture = r_texture_black;
7666 t->nmaptexture = r_texture_blanknormalmap;
7667 t->glosstexture = r_texture_black;
7668 t->glowtexture = NULL;
7669 t->fogtexture = NULL;
7670 t->reflectmasktexture = NULL;
7671 t->backgroundbasetexture = NULL;
7672 t->backgroundnmaptexture = r_texture_blanknormalmap;
7673 t->backgroundglosstexture = r_texture_black;
7674 t->backgroundglowtexture = NULL;
7675 t->specularscale = 0;
7676 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7679 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7680 VectorClear(t->dlightcolor);
7681 t->currentnumlayers = 0;
7682 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7684 int blendfunc1, blendfunc2;
7686 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7688 blendfunc1 = GL_SRC_ALPHA;
7689 blendfunc2 = GL_ONE;
7691 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7693 blendfunc1 = GL_SRC_ALPHA;
7694 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7696 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7698 blendfunc1 = t->customblendfunc[0];
7699 blendfunc2 = t->customblendfunc[1];
7703 blendfunc1 = GL_ONE;
7704 blendfunc2 = GL_ZERO;
7706 // don't colormod evilblend textures
7707 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7708 VectorSet(t->lightmapcolor, 1, 1, 1);
7709 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7710 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7712 // fullbright is not affected by r_refdef.lightmapintensity
7713 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]);
7714 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7715 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]);
7716 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7717 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]);
7721 vec3_t ambientcolor;
7723 // set the color tint used for lights affecting this surface
7724 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7726 // q3bsp has no lightmap updates, so the lightstylevalue that
7727 // would normally be baked into the lightmap must be
7728 // applied to the color
7729 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7730 if (model->type == mod_brushq3)
7731 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7732 colorscale *= r_refdef.lightmapintensity;
7733 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7734 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7735 // basic lit geometry
7736 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]);
7737 // add pants/shirt if needed
7738 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7739 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]);
7740 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7741 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]);
7742 // now add ambient passes if needed
7743 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7745 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]);
7746 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7747 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]);
7748 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7749 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]);
7752 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7753 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]);
7754 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7756 // if this is opaque use alpha blend which will darken the earlier
7759 // if this is an alpha blended material, all the earlier passes
7760 // were darkened by fog already, so we only need to add the fog
7761 // color ontop through the fog mask texture
7763 // if this is an additive blended material, all the earlier passes
7764 // were darkened by fog already, and we should not add fog color
7765 // (because the background was not darkened, there is no fog color
7766 // that was lost behind it).
7767 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]);
7771 return t->currentframe;
7774 rsurfacestate_t rsurface;
7776 void RSurf_ActiveWorldEntity(void)
7778 dp_model_t *model = r_refdef.scene.worldmodel;
7779 //if (rsurface.entity == r_refdef.scene.worldentity)
7781 rsurface.entity = r_refdef.scene.worldentity;
7782 rsurface.skeleton = NULL;
7783 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7784 rsurface.ent_skinnum = 0;
7785 rsurface.ent_qwskin = -1;
7786 rsurface.ent_shadertime = 0;
7787 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7788 rsurface.matrix = identitymatrix;
7789 rsurface.inversematrix = identitymatrix;
7790 rsurface.matrixscale = 1;
7791 rsurface.inversematrixscale = 1;
7792 R_EntityMatrix(&identitymatrix);
7793 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7794 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7795 rsurface.fograngerecip = r_refdef.fograngerecip;
7796 rsurface.fogheightfade = r_refdef.fogheightfade;
7797 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7798 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7799 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7800 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7801 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7802 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7803 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7804 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7805 rsurface.colormod[3] = 1;
7806 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);
7807 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7808 rsurface.frameblend[0].lerp = 1;
7809 rsurface.ent_alttextures = false;
7810 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7811 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7812 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7813 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7814 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7815 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7816 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7817 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7818 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7819 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7820 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7821 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7822 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7823 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7824 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7825 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7826 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7827 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7828 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7829 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7830 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7831 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7832 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7833 rsurface.modelelement3i = model->surfmesh.data_element3i;
7834 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7835 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7836 rsurface.modelelement3s = model->surfmesh.data_element3s;
7837 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7838 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7839 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7840 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7841 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7842 rsurface.modelsurfaces = model->data_surfaces;
7843 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7844 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7845 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7846 rsurface.modelgeneratedvertex = false;
7847 rsurface.batchgeneratedvertex = false;
7848 rsurface.batchfirstvertex = 0;
7849 rsurface.batchnumvertices = 0;
7850 rsurface.batchfirsttriangle = 0;
7851 rsurface.batchnumtriangles = 0;
7852 rsurface.batchvertex3f = NULL;
7853 rsurface.batchvertex3f_vertexbuffer = NULL;
7854 rsurface.batchvertex3f_bufferoffset = 0;
7855 rsurface.batchsvector3f = NULL;
7856 rsurface.batchsvector3f_vertexbuffer = NULL;
7857 rsurface.batchsvector3f_bufferoffset = 0;
7858 rsurface.batchtvector3f = NULL;
7859 rsurface.batchtvector3f_vertexbuffer = NULL;
7860 rsurface.batchtvector3f_bufferoffset = 0;
7861 rsurface.batchnormal3f = NULL;
7862 rsurface.batchnormal3f_vertexbuffer = NULL;
7863 rsurface.batchnormal3f_bufferoffset = 0;
7864 rsurface.batchlightmapcolor4f = NULL;
7865 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7866 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7867 rsurface.batchtexcoordtexture2f = NULL;
7868 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7869 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7870 rsurface.batchtexcoordlightmap2f = NULL;
7871 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7872 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7873 rsurface.batchvertexmesh = NULL;
7874 rsurface.batchvertexmeshbuffer = NULL;
7875 rsurface.batchvertex3fbuffer = NULL;
7876 rsurface.batchelement3i = NULL;
7877 rsurface.batchelement3i_indexbuffer = NULL;
7878 rsurface.batchelement3i_bufferoffset = 0;
7879 rsurface.batchelement3s = NULL;
7880 rsurface.batchelement3s_indexbuffer = NULL;
7881 rsurface.batchelement3s_bufferoffset = 0;
7882 rsurface.passcolor4f = NULL;
7883 rsurface.passcolor4f_vertexbuffer = NULL;
7884 rsurface.passcolor4f_bufferoffset = 0;
7887 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7889 dp_model_t *model = ent->model;
7890 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7892 rsurface.entity = (entity_render_t *)ent;
7893 rsurface.skeleton = ent->skeleton;
7894 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7895 rsurface.ent_skinnum = ent->skinnum;
7896 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;
7897 rsurface.ent_shadertime = ent->shadertime;
7898 rsurface.ent_flags = ent->flags;
7899 rsurface.matrix = ent->matrix;
7900 rsurface.inversematrix = ent->inversematrix;
7901 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7902 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7903 R_EntityMatrix(&rsurface.matrix);
7904 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7905 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7906 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7907 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7908 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7909 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7910 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7911 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7912 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7913 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7914 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7915 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7916 rsurface.colormod[3] = ent->alpha;
7917 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7918 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7919 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7920 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7921 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7922 if (ent->model->brush.submodel && !prepass)
7924 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7925 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7927 if (model->surfmesh.isanimated && model->AnimateVertices)
7929 if (ent->animcache_vertex3f)
7931 rsurface.modelvertex3f = ent->animcache_vertex3f;
7932 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7933 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7934 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7935 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7936 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7937 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7939 else if (wanttangents)
7941 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7942 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7943 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7944 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7945 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7946 rsurface.modelvertexmesh = NULL;
7947 rsurface.modelvertexmeshbuffer = NULL;
7948 rsurface.modelvertex3fbuffer = NULL;
7950 else if (wantnormals)
7952 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7953 rsurface.modelsvector3f = NULL;
7954 rsurface.modeltvector3f = NULL;
7955 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7956 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7957 rsurface.modelvertexmesh = NULL;
7958 rsurface.modelvertexmeshbuffer = NULL;
7959 rsurface.modelvertex3fbuffer = NULL;
7963 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7964 rsurface.modelsvector3f = NULL;
7965 rsurface.modeltvector3f = NULL;
7966 rsurface.modelnormal3f = NULL;
7967 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7968 rsurface.modelvertexmesh = NULL;
7969 rsurface.modelvertexmeshbuffer = NULL;
7970 rsurface.modelvertex3fbuffer = NULL;
7972 rsurface.modelvertex3f_vertexbuffer = 0;
7973 rsurface.modelvertex3f_bufferoffset = 0;
7974 rsurface.modelsvector3f_vertexbuffer = 0;
7975 rsurface.modelsvector3f_bufferoffset = 0;
7976 rsurface.modeltvector3f_vertexbuffer = 0;
7977 rsurface.modeltvector3f_bufferoffset = 0;
7978 rsurface.modelnormal3f_vertexbuffer = 0;
7979 rsurface.modelnormal3f_bufferoffset = 0;
7980 rsurface.modelgeneratedvertex = true;
7984 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7985 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7986 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7987 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7988 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7989 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7990 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7991 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7992 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7993 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7994 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7995 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7996 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7997 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7998 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7999 rsurface.modelgeneratedvertex = false;
8001 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8002 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8003 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8004 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8005 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8006 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8007 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8008 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8009 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8010 rsurface.modelelement3i = model->surfmesh.data_element3i;
8011 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8012 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8013 rsurface.modelelement3s = model->surfmesh.data_element3s;
8014 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8015 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8016 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8017 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8018 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8019 rsurface.modelsurfaces = model->data_surfaces;
8020 rsurface.batchgeneratedvertex = false;
8021 rsurface.batchfirstvertex = 0;
8022 rsurface.batchnumvertices = 0;
8023 rsurface.batchfirsttriangle = 0;
8024 rsurface.batchnumtriangles = 0;
8025 rsurface.batchvertex3f = NULL;
8026 rsurface.batchvertex3f_vertexbuffer = NULL;
8027 rsurface.batchvertex3f_bufferoffset = 0;
8028 rsurface.batchsvector3f = NULL;
8029 rsurface.batchsvector3f_vertexbuffer = NULL;
8030 rsurface.batchsvector3f_bufferoffset = 0;
8031 rsurface.batchtvector3f = NULL;
8032 rsurface.batchtvector3f_vertexbuffer = NULL;
8033 rsurface.batchtvector3f_bufferoffset = 0;
8034 rsurface.batchnormal3f = NULL;
8035 rsurface.batchnormal3f_vertexbuffer = NULL;
8036 rsurface.batchnormal3f_bufferoffset = 0;
8037 rsurface.batchlightmapcolor4f = NULL;
8038 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8039 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8040 rsurface.batchtexcoordtexture2f = NULL;
8041 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8042 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8043 rsurface.batchtexcoordlightmap2f = NULL;
8044 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8045 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8046 rsurface.batchvertexmesh = NULL;
8047 rsurface.batchvertexmeshbuffer = NULL;
8048 rsurface.batchvertex3fbuffer = NULL;
8049 rsurface.batchelement3i = NULL;
8050 rsurface.batchelement3i_indexbuffer = NULL;
8051 rsurface.batchelement3i_bufferoffset = 0;
8052 rsurface.batchelement3s = NULL;
8053 rsurface.batchelement3s_indexbuffer = NULL;
8054 rsurface.batchelement3s_bufferoffset = 0;
8055 rsurface.passcolor4f = NULL;
8056 rsurface.passcolor4f_vertexbuffer = NULL;
8057 rsurface.passcolor4f_bufferoffset = 0;
8060 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)
8062 rsurface.entity = r_refdef.scene.worldentity;
8063 rsurface.skeleton = NULL;
8064 rsurface.ent_skinnum = 0;
8065 rsurface.ent_qwskin = -1;
8066 rsurface.ent_shadertime = shadertime;
8067 rsurface.ent_flags = entflags;
8068 rsurface.modelnumvertices = numvertices;
8069 rsurface.modelnumtriangles = numtriangles;
8070 rsurface.matrix = *matrix;
8071 rsurface.inversematrix = *inversematrix;
8072 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8073 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8074 R_EntityMatrix(&rsurface.matrix);
8075 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8076 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8077 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8078 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8079 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8080 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8081 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8082 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8083 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8084 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8085 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8086 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8087 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);
8088 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8089 rsurface.frameblend[0].lerp = 1;
8090 rsurface.ent_alttextures = false;
8091 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8092 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8095 rsurface.modelvertex3f = (float *)vertex3f;
8096 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8097 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8098 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8100 else if (wantnormals)
8102 rsurface.modelvertex3f = (float *)vertex3f;
8103 rsurface.modelsvector3f = NULL;
8104 rsurface.modeltvector3f = NULL;
8105 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8109 rsurface.modelvertex3f = (float *)vertex3f;
8110 rsurface.modelsvector3f = NULL;
8111 rsurface.modeltvector3f = NULL;
8112 rsurface.modelnormal3f = NULL;
8114 rsurface.modelvertexmesh = NULL;
8115 rsurface.modelvertexmeshbuffer = NULL;
8116 rsurface.modelvertex3fbuffer = NULL;
8117 rsurface.modelvertex3f_vertexbuffer = 0;
8118 rsurface.modelvertex3f_bufferoffset = 0;
8119 rsurface.modelsvector3f_vertexbuffer = 0;
8120 rsurface.modelsvector3f_bufferoffset = 0;
8121 rsurface.modeltvector3f_vertexbuffer = 0;
8122 rsurface.modeltvector3f_bufferoffset = 0;
8123 rsurface.modelnormal3f_vertexbuffer = 0;
8124 rsurface.modelnormal3f_bufferoffset = 0;
8125 rsurface.modelgeneratedvertex = true;
8126 rsurface.modellightmapcolor4f = (float *)color4f;
8127 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8128 rsurface.modellightmapcolor4f_bufferoffset = 0;
8129 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8130 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8131 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8132 rsurface.modeltexcoordlightmap2f = NULL;
8133 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8134 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8135 rsurface.modelelement3i = (int *)element3i;
8136 rsurface.modelelement3i_indexbuffer = NULL;
8137 rsurface.modelelement3i_bufferoffset = 0;
8138 rsurface.modelelement3s = (unsigned short *)element3s;
8139 rsurface.modelelement3s_indexbuffer = NULL;
8140 rsurface.modelelement3s_bufferoffset = 0;
8141 rsurface.modellightmapoffsets = NULL;
8142 rsurface.modelsurfaces = NULL;
8143 rsurface.batchgeneratedvertex = false;
8144 rsurface.batchfirstvertex = 0;
8145 rsurface.batchnumvertices = 0;
8146 rsurface.batchfirsttriangle = 0;
8147 rsurface.batchnumtriangles = 0;
8148 rsurface.batchvertex3f = NULL;
8149 rsurface.batchvertex3f_vertexbuffer = NULL;
8150 rsurface.batchvertex3f_bufferoffset = 0;
8151 rsurface.batchsvector3f = NULL;
8152 rsurface.batchsvector3f_vertexbuffer = NULL;
8153 rsurface.batchsvector3f_bufferoffset = 0;
8154 rsurface.batchtvector3f = NULL;
8155 rsurface.batchtvector3f_vertexbuffer = NULL;
8156 rsurface.batchtvector3f_bufferoffset = 0;
8157 rsurface.batchnormal3f = NULL;
8158 rsurface.batchnormal3f_vertexbuffer = NULL;
8159 rsurface.batchnormal3f_bufferoffset = 0;
8160 rsurface.batchlightmapcolor4f = NULL;
8161 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8162 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8163 rsurface.batchtexcoordtexture2f = NULL;
8164 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8165 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8166 rsurface.batchtexcoordlightmap2f = NULL;
8167 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8168 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8169 rsurface.batchvertexmesh = NULL;
8170 rsurface.batchvertexmeshbuffer = NULL;
8171 rsurface.batchvertex3fbuffer = NULL;
8172 rsurface.batchelement3i = NULL;
8173 rsurface.batchelement3i_indexbuffer = NULL;
8174 rsurface.batchelement3i_bufferoffset = 0;
8175 rsurface.batchelement3s = NULL;
8176 rsurface.batchelement3s_indexbuffer = NULL;
8177 rsurface.batchelement3s_bufferoffset = 0;
8178 rsurface.passcolor4f = NULL;
8179 rsurface.passcolor4f_vertexbuffer = NULL;
8180 rsurface.passcolor4f_bufferoffset = 0;
8182 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8184 if ((wantnormals || wanttangents) && !normal3f)
8186 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8187 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8189 if (wanttangents && !svector3f)
8191 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8192 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8193 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8198 float RSurf_FogPoint(const float *v)
8200 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8201 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8202 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8203 float FogHeightFade = r_refdef.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(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8211 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8214 float RSurf_FogVertex(const float *v)
8216 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8217 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8218 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8219 float FogHeightFade = rsurface.fogheightfade;
8221 unsigned int fogmasktableindex;
8222 if (r_refdef.fogplaneviewabove)
8223 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8225 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8226 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8227 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8230 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8233 for (i = 0;i < numelements;i++)
8234 outelement3i[i] = inelement3i[i] + adjust;
8237 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8238 extern cvar_t gl_vbo;
8239 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8247 int surfacefirsttriangle;
8248 int surfacenumtriangles;
8249 int surfacefirstvertex;
8250 int surfaceendvertex;
8251 int surfacenumvertices;
8252 int batchnumvertices;
8253 int batchnumtriangles;
8257 qboolean dynamicvertex;
8261 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8263 q3shaderinfo_deform_t *deform;
8264 const msurface_t *surface, *firstsurface;
8265 r_vertexmesh_t *vertexmesh;
8266 if (!texturenumsurfaces)
8268 // find vertex range of this surface batch
8270 firstsurface = texturesurfacelist[0];
8271 firsttriangle = firstsurface->num_firsttriangle;
8272 batchnumvertices = 0;
8273 batchnumtriangles = 0;
8274 firstvertex = endvertex = firstsurface->num_firstvertex;
8275 for (i = 0;i < texturenumsurfaces;i++)
8277 surface = texturesurfacelist[i];
8278 if (surface != firstsurface + i)
8280 surfacefirstvertex = surface->num_firstvertex;
8281 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8282 surfacenumvertices = surface->num_vertices;
8283 surfacenumtriangles = surface->num_triangles;
8284 if (firstvertex > surfacefirstvertex)
8285 firstvertex = surfacefirstvertex;
8286 if (endvertex < surfaceendvertex)
8287 endvertex = surfaceendvertex;
8288 batchnumvertices += surfacenumvertices;
8289 batchnumtriangles += surfacenumtriangles;
8292 // we now know the vertex range used, and if there are any gaps in it
8293 rsurface.batchfirstvertex = firstvertex;
8294 rsurface.batchnumvertices = endvertex - firstvertex;
8295 rsurface.batchfirsttriangle = firsttriangle;
8296 rsurface.batchnumtriangles = batchnumtriangles;
8298 // this variable holds flags for which properties have been updated that
8299 // may require regenerating vertexmesh array...
8302 // check if any dynamic vertex processing must occur
8303 dynamicvertex = false;
8305 // if there is a chance of animated vertex colors, it's a dynamic batch
8306 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8308 dynamicvertex = true;
8309 batchneed |= BATCHNEED_NOGAPS;
8310 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8313 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8315 switch (deform->deform)
8318 case Q3DEFORM_PROJECTIONSHADOW:
8319 case Q3DEFORM_TEXT0:
8320 case Q3DEFORM_TEXT1:
8321 case Q3DEFORM_TEXT2:
8322 case Q3DEFORM_TEXT3:
8323 case Q3DEFORM_TEXT4:
8324 case Q3DEFORM_TEXT5:
8325 case Q3DEFORM_TEXT6:
8326 case Q3DEFORM_TEXT7:
8329 case Q3DEFORM_AUTOSPRITE:
8330 dynamicvertex = true;
8331 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8332 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8334 case Q3DEFORM_AUTOSPRITE2:
8335 dynamicvertex = true;
8336 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8337 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8339 case Q3DEFORM_NORMAL:
8340 dynamicvertex = true;
8341 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8342 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8345 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8346 break; // if wavefunc is a nop, ignore this transform
8347 dynamicvertex = true;
8348 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8349 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8351 case Q3DEFORM_BULGE:
8352 dynamicvertex = true;
8353 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8354 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8357 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8358 break; // if wavefunc is a nop, ignore this transform
8359 dynamicvertex = true;
8360 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8361 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8365 switch(rsurface.texture->tcgen.tcgen)
8368 case Q3TCGEN_TEXTURE:
8370 case Q3TCGEN_LIGHTMAP:
8371 dynamicvertex = true;
8372 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8373 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8375 case Q3TCGEN_VECTOR:
8376 dynamicvertex = true;
8377 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8378 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8380 case Q3TCGEN_ENVIRONMENT:
8381 dynamicvertex = true;
8382 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8383 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8386 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8388 dynamicvertex = true;
8389 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8390 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8393 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8395 dynamicvertex = true;
8396 batchneed |= BATCHNEED_NOGAPS;
8397 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8400 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8402 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8403 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8404 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8405 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8406 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8407 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8408 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8411 // when the model data has no vertex buffer (dynamic mesh), we need to
8413 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8414 batchneed |= BATCHNEED_NOGAPS;
8416 // if needsupdate, we have to do a dynamic vertex batch for sure
8417 if (needsupdate & batchneed)
8418 dynamicvertex = true;
8420 // see if we need to build vertexmesh from arrays
8421 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8422 dynamicvertex = true;
8424 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8425 // also some drivers strongly dislike firstvertex
8426 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8427 dynamicvertex = true;
8429 rsurface.batchvertex3f = rsurface.modelvertex3f;
8430 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8431 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8432 rsurface.batchsvector3f = rsurface.modelsvector3f;
8433 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8434 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8435 rsurface.batchtvector3f = rsurface.modeltvector3f;
8436 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8437 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8438 rsurface.batchnormal3f = rsurface.modelnormal3f;
8439 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8440 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8441 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8442 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8443 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8444 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8445 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8446 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8447 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8448 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8449 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8450 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8451 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8452 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8453 rsurface.batchelement3i = rsurface.modelelement3i;
8454 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8455 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8456 rsurface.batchelement3s = rsurface.modelelement3s;
8457 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8458 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8460 // if any dynamic vertex processing has to occur in software, we copy the
8461 // entire surface list together before processing to rebase the vertices
8462 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8464 // if any gaps exist and we do not have a static vertex buffer, we have to
8465 // copy the surface list together to avoid wasting upload bandwidth on the
8466 // vertices in the gaps.
8468 // if gaps exist and we have a static vertex buffer, we still have to
8469 // combine the index buffer ranges into one dynamic index buffer.
8471 // in all cases we end up with data that can be drawn in one call.
8475 // static vertex data, just set pointers...
8476 rsurface.batchgeneratedvertex = false;
8477 // if there are gaps, we want to build a combined index buffer,
8478 // otherwise use the original static buffer with an appropriate offset
8481 // build a new triangle elements array for this batch
8482 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8483 rsurface.batchfirsttriangle = 0;
8485 for (i = 0;i < texturenumsurfaces;i++)
8487 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8488 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8489 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8490 numtriangles += surfacenumtriangles;
8492 rsurface.batchelement3i_indexbuffer = NULL;
8493 rsurface.batchelement3i_bufferoffset = 0;
8494 rsurface.batchelement3s = NULL;
8495 rsurface.batchelement3s_indexbuffer = NULL;
8496 rsurface.batchelement3s_bufferoffset = 0;
8497 if (endvertex <= 65536)
8499 // make a 16bit (unsigned short) index array if possible
8500 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8501 for (i = 0;i < numtriangles*3;i++)
8502 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8508 // something needs software processing, do it for real...
8509 // we only directly handle separate array data in this case and then
8510 // generate interleaved data if needed...
8511 rsurface.batchgeneratedvertex = true;
8513 // now copy the vertex data into a combined array and make an index array
8514 // (this is what Quake3 does all the time)
8515 //if (gaps || rsurface.batchfirstvertex)
8517 rsurface.batchvertex3fbuffer = NULL;
8518 rsurface.batchvertexmesh = NULL;
8519 rsurface.batchvertexmeshbuffer = NULL;
8520 rsurface.batchvertex3f = NULL;
8521 rsurface.batchvertex3f_vertexbuffer = NULL;
8522 rsurface.batchvertex3f_bufferoffset = 0;
8523 rsurface.batchsvector3f = NULL;
8524 rsurface.batchsvector3f_vertexbuffer = NULL;
8525 rsurface.batchsvector3f_bufferoffset = 0;
8526 rsurface.batchtvector3f = NULL;
8527 rsurface.batchtvector3f_vertexbuffer = NULL;
8528 rsurface.batchtvector3f_bufferoffset = 0;
8529 rsurface.batchnormal3f = NULL;
8530 rsurface.batchnormal3f_vertexbuffer = NULL;
8531 rsurface.batchnormal3f_bufferoffset = 0;
8532 rsurface.batchlightmapcolor4f = NULL;
8533 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8534 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8535 rsurface.batchtexcoordtexture2f = NULL;
8536 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8537 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8538 rsurface.batchtexcoordlightmap2f = NULL;
8539 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8540 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8541 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8542 rsurface.batchelement3i_indexbuffer = NULL;
8543 rsurface.batchelement3i_bufferoffset = 0;
8544 rsurface.batchelement3s = NULL;
8545 rsurface.batchelement3s_indexbuffer = NULL;
8546 rsurface.batchelement3s_bufferoffset = 0;
8547 // we'll only be setting up certain arrays as needed
8548 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8549 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8550 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8551 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8552 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8553 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8554 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8556 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8557 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8559 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8560 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8561 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8562 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8563 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8564 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8567 for (i = 0;i < texturenumsurfaces;i++)
8569 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8570 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8571 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8572 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8573 // copy only the data requested
8574 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8575 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8576 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8578 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8579 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8580 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8581 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8582 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8584 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8585 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8587 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8588 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8589 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8590 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8591 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8592 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8594 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8595 numvertices += surfacenumvertices;
8596 numtriangles += surfacenumtriangles;
8599 // generate a 16bit index array as well if possible
8600 // (in general, dynamic batches fit)
8601 if (numvertices <= 65536)
8603 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8604 for (i = 0;i < numtriangles*3;i++)
8605 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8608 // since we've copied everything, the batch now starts at 0
8609 rsurface.batchfirstvertex = 0;
8610 rsurface.batchnumvertices = batchnumvertices;
8611 rsurface.batchfirsttriangle = 0;
8612 rsurface.batchnumtriangles = batchnumtriangles;
8615 // q1bsp surfaces rendered in vertex color mode have to have colors
8616 // calculated based on lightstyles
8617 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8619 // generate color arrays for the surfaces in this list
8624 const unsigned char *lm;
8625 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8626 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8627 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8629 for (i = 0;i < texturenumsurfaces;i++)
8631 surface = texturesurfacelist[i];
8632 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8633 surfacenumvertices = surface->num_vertices;
8634 if (surface->lightmapinfo->samples)
8636 for (j = 0;j < surfacenumvertices;j++)
8638 lm = surface->lightmapinfo->samples + offsets[j];
8639 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8640 VectorScale(lm, scale, c);
8641 if (surface->lightmapinfo->styles[1] != 255)
8643 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8645 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8646 VectorMA(c, scale, lm, c);
8647 if (surface->lightmapinfo->styles[2] != 255)
8650 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8651 VectorMA(c, scale, lm, c);
8652 if (surface->lightmapinfo->styles[3] != 255)
8655 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8656 VectorMA(c, scale, lm, c);
8663 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);
8669 for (j = 0;j < surfacenumvertices;j++)
8671 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8678 // if vertices are deformed (sprite flares and things in maps, possibly
8679 // water waves, bulges and other deformations), modify the copied vertices
8681 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8683 switch (deform->deform)
8686 case Q3DEFORM_PROJECTIONSHADOW:
8687 case Q3DEFORM_TEXT0:
8688 case Q3DEFORM_TEXT1:
8689 case Q3DEFORM_TEXT2:
8690 case Q3DEFORM_TEXT3:
8691 case Q3DEFORM_TEXT4:
8692 case Q3DEFORM_TEXT5:
8693 case Q3DEFORM_TEXT6:
8694 case Q3DEFORM_TEXT7:
8697 case Q3DEFORM_AUTOSPRITE:
8698 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8699 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8700 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8701 VectorNormalize(newforward);
8702 VectorNormalize(newright);
8703 VectorNormalize(newup);
8704 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8705 // rsurface.batchvertex3f_vertexbuffer = NULL;
8706 // rsurface.batchvertex3f_bufferoffset = 0;
8707 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8708 // rsurface.batchsvector3f_vertexbuffer = NULL;
8709 // rsurface.batchsvector3f_bufferoffset = 0;
8710 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8711 // rsurface.batchtvector3f_vertexbuffer = NULL;
8712 // rsurface.batchtvector3f_bufferoffset = 0;
8713 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8714 // rsurface.batchnormal3f_vertexbuffer = NULL;
8715 // rsurface.batchnormal3f_bufferoffset = 0;
8716 // a single autosprite surface can contain multiple sprites...
8717 for (j = 0;j < batchnumvertices - 3;j += 4)
8719 VectorClear(center);
8720 for (i = 0;i < 4;i++)
8721 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8722 VectorScale(center, 0.25f, center);
8723 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8724 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8725 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8726 for (i = 0;i < 4;i++)
8728 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8729 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8732 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8733 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8734 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);
8736 case Q3DEFORM_AUTOSPRITE2:
8737 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8738 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8739 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8740 VectorNormalize(newforward);
8741 VectorNormalize(newright);
8742 VectorNormalize(newup);
8743 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8744 // rsurface.batchvertex3f_vertexbuffer = NULL;
8745 // rsurface.batchvertex3f_bufferoffset = 0;
8747 const float *v1, *v2;
8757 memset(shortest, 0, sizeof(shortest));
8758 // a single autosprite surface can contain multiple sprites...
8759 for (j = 0;j < batchnumvertices - 3;j += 4)
8761 VectorClear(center);
8762 for (i = 0;i < 4;i++)
8763 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8764 VectorScale(center, 0.25f, center);
8765 // find the two shortest edges, then use them to define the
8766 // axis vectors for rotating around the central axis
8767 for (i = 0;i < 6;i++)
8769 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8770 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8771 l = VectorDistance2(v1, v2);
8772 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8774 l += (1.0f / 1024.0f);
8775 if (shortest[0].length2 > l || i == 0)
8777 shortest[1] = shortest[0];
8778 shortest[0].length2 = l;
8779 shortest[0].v1 = v1;
8780 shortest[0].v2 = v2;
8782 else if (shortest[1].length2 > l || i == 1)
8784 shortest[1].length2 = l;
8785 shortest[1].v1 = v1;
8786 shortest[1].v2 = v2;
8789 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8790 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8791 // this calculates the right vector from the shortest edge
8792 // and the up vector from the edge midpoints
8793 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8794 VectorNormalize(right);
8795 VectorSubtract(end, start, up);
8796 VectorNormalize(up);
8797 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8798 VectorSubtract(rsurface.localvieworigin, center, forward);
8799 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8800 VectorNegate(forward, forward);
8801 VectorReflect(forward, 0, up, forward);
8802 VectorNormalize(forward);
8803 CrossProduct(up, forward, newright);
8804 VectorNormalize(newright);
8805 // rotate the quad around the up axis vector, this is made
8806 // especially easy by the fact we know the quad is flat,
8807 // so we only have to subtract the center position and
8808 // measure distance along the right vector, and then
8809 // multiply that by the newright vector and add back the
8811 // we also need to subtract the old position to undo the
8812 // displacement from the center, which we do with a
8813 // DotProduct, the subtraction/addition of center is also
8814 // optimized into DotProducts here
8815 l = DotProduct(right, center);
8816 for (i = 0;i < 4;i++)
8818 v1 = rsurface.batchvertex3f + 3*(j+i);
8819 f = DotProduct(right, v1) - l;
8820 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8824 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8826 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8827 // rsurface.batchnormal3f_vertexbuffer = NULL;
8828 // rsurface.batchnormal3f_bufferoffset = 0;
8829 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8831 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8833 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8834 // rsurface.batchsvector3f_vertexbuffer = NULL;
8835 // rsurface.batchsvector3f_bufferoffset = 0;
8836 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8837 // rsurface.batchtvector3f_vertexbuffer = NULL;
8838 // rsurface.batchtvector3f_bufferoffset = 0;
8839 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);
8842 case Q3DEFORM_NORMAL:
8843 // deform the normals to make reflections wavey
8844 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8845 rsurface.batchnormal3f_vertexbuffer = NULL;
8846 rsurface.batchnormal3f_bufferoffset = 0;
8847 for (j = 0;j < batchnumvertices;j++)
8850 float *normal = rsurface.batchnormal3f + 3*j;
8851 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8852 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8853 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]);
8854 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]);
8855 VectorNormalize(normal);
8857 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8859 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8860 // rsurface.batchsvector3f_vertexbuffer = NULL;
8861 // rsurface.batchsvector3f_bufferoffset = 0;
8862 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8863 // rsurface.batchtvector3f_vertexbuffer = NULL;
8864 // rsurface.batchtvector3f_bufferoffset = 0;
8865 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);
8869 // deform vertex array to make wavey water and flags and such
8870 waveparms[0] = deform->waveparms[0];
8871 waveparms[1] = deform->waveparms[1];
8872 waveparms[2] = deform->waveparms[2];
8873 waveparms[3] = deform->waveparms[3];
8874 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8875 break; // if wavefunc is a nop, don't make a dynamic vertex array
8876 // this is how a divisor of vertex influence on deformation
8877 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8878 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8879 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8880 // rsurface.batchvertex3f_vertexbuffer = NULL;
8881 // rsurface.batchvertex3f_bufferoffset = 0;
8882 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8883 // rsurface.batchnormal3f_vertexbuffer = NULL;
8884 // rsurface.batchnormal3f_bufferoffset = 0;
8885 for (j = 0;j < batchnumvertices;j++)
8887 // if the wavefunc depends on time, evaluate it per-vertex
8890 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8891 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8893 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8895 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8896 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8897 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8899 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8900 // rsurface.batchsvector3f_vertexbuffer = NULL;
8901 // rsurface.batchsvector3f_bufferoffset = 0;
8902 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8903 // rsurface.batchtvector3f_vertexbuffer = NULL;
8904 // rsurface.batchtvector3f_bufferoffset = 0;
8905 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);
8908 case Q3DEFORM_BULGE:
8909 // deform vertex array to make the surface have moving bulges
8910 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8911 // rsurface.batchvertex3f_vertexbuffer = NULL;
8912 // rsurface.batchvertex3f_bufferoffset = 0;
8913 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8914 // rsurface.batchnormal3f_vertexbuffer = NULL;
8915 // rsurface.batchnormal3f_bufferoffset = 0;
8916 for (j = 0;j < batchnumvertices;j++)
8918 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8919 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8921 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8922 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8923 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8925 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8926 // rsurface.batchsvector3f_vertexbuffer = NULL;
8927 // rsurface.batchsvector3f_bufferoffset = 0;
8928 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8929 // rsurface.batchtvector3f_vertexbuffer = NULL;
8930 // rsurface.batchtvector3f_bufferoffset = 0;
8931 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);
8935 // deform vertex array
8936 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8937 break; // if wavefunc is a nop, don't make a dynamic vertex array
8938 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8939 VectorScale(deform->parms, scale, waveparms);
8940 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8941 // rsurface.batchvertex3f_vertexbuffer = NULL;
8942 // rsurface.batchvertex3f_bufferoffset = 0;
8943 for (j = 0;j < batchnumvertices;j++)
8944 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8949 // generate texcoords based on the chosen texcoord source
8950 switch(rsurface.texture->tcgen.tcgen)
8953 case Q3TCGEN_TEXTURE:
8955 case Q3TCGEN_LIGHTMAP:
8956 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8957 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8958 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8959 if (rsurface.batchtexcoordlightmap2f)
8960 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8962 case Q3TCGEN_VECTOR:
8963 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8964 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8965 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8966 for (j = 0;j < batchnumvertices;j++)
8968 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8969 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8972 case Q3TCGEN_ENVIRONMENT:
8973 // make environment reflections using a spheremap
8974 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8975 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8976 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8977 for (j = 0;j < batchnumvertices;j++)
8979 // identical to Q3A's method, but executed in worldspace so
8980 // carried models can be shiny too
8982 float viewer[3], d, reflected[3], worldreflected[3];
8984 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8985 // VectorNormalize(viewer);
8987 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8989 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8990 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8991 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8992 // note: this is proportinal to viewer, so we can normalize later
8994 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8995 VectorNormalize(worldreflected);
8997 // note: this sphere map only uses world x and z!
8998 // so positive and negative y will LOOK THE SAME.
8999 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9000 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9004 // the only tcmod that needs software vertex processing is turbulent, so
9005 // check for it here and apply the changes if needed
9006 // and we only support that as the first one
9007 // (handling a mixture of turbulent and other tcmods would be problematic
9008 // without punting it entirely to a software path)
9009 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9011 amplitude = rsurface.texture->tcmods[0].parms[1];
9012 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9013 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9014 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9015 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9016 for (j = 0;j < batchnumvertices;j++)
9018 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);
9019 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9023 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9025 // convert the modified arrays to vertex structs
9026 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9027 // rsurface.batchvertexmeshbuffer = NULL;
9028 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9029 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9030 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9031 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9032 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9033 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9034 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9036 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9038 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9039 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9042 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9043 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9044 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9045 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9046 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9047 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9048 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9049 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9050 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9054 void RSurf_DrawBatch(void)
9056 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9057 // through the pipeline, killing it earlier in the pipeline would have
9058 // per-surface overhead rather than per-batch overhead, so it's best to
9059 // reject it here, before it hits glDraw.
9060 if (rsurface.batchnumtriangles == 0)
9063 // batch debugging code
9064 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9070 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9071 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9074 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9076 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9078 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9079 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);
9086 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);
9089 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9091 // pick the closest matching water plane
9092 int planeindex, vertexindex, bestplaneindex = -1;
9096 r_waterstate_waterplane_t *p;
9097 qboolean prepared = false;
9099 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9101 if(p->camera_entity != rsurface.texture->camera_entity)
9106 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9108 if(rsurface.batchnumvertices == 0)
9111 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9113 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9114 d += fabs(PlaneDiff(vert, &p->plane));
9116 if (bestd > d || bestplaneindex < 0)
9119 bestplaneindex = planeindex;
9122 return bestplaneindex;
9123 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9124 // this situation though, as it might be better to render single larger
9125 // batches with useless stuff (backface culled for example) than to
9126 // render multiple smaller batches
9129 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9132 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9133 rsurface.passcolor4f_vertexbuffer = 0;
9134 rsurface.passcolor4f_bufferoffset = 0;
9135 for (i = 0;i < rsurface.batchnumvertices;i++)
9136 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9139 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9146 if (rsurface.passcolor4f)
9148 // generate color arrays
9149 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9150 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9151 rsurface.passcolor4f_vertexbuffer = 0;
9152 rsurface.passcolor4f_bufferoffset = 0;
9153 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)
9155 f = RSurf_FogVertex(v);
9164 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9165 rsurface.passcolor4f_vertexbuffer = 0;
9166 rsurface.passcolor4f_bufferoffset = 0;
9167 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9169 f = RSurf_FogVertex(v);
9178 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9185 if (!rsurface.passcolor4f)
9187 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9188 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9189 rsurface.passcolor4f_vertexbuffer = 0;
9190 rsurface.passcolor4f_bufferoffset = 0;
9191 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)
9193 f = RSurf_FogVertex(v);
9194 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9195 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9196 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9201 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9206 if (!rsurface.passcolor4f)
9208 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9209 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9210 rsurface.passcolor4f_vertexbuffer = 0;
9211 rsurface.passcolor4f_bufferoffset = 0;
9212 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9221 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9226 if (!rsurface.passcolor4f)
9228 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9229 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9230 rsurface.passcolor4f_vertexbuffer = 0;
9231 rsurface.passcolor4f_bufferoffset = 0;
9232 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9234 c2[0] = c[0] + r_refdef.scene.ambient;
9235 c2[1] = c[1] + r_refdef.scene.ambient;
9236 c2[2] = c[2] + r_refdef.scene.ambient;
9241 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9244 rsurface.passcolor4f = NULL;
9245 rsurface.passcolor4f_vertexbuffer = 0;
9246 rsurface.passcolor4f_bufferoffset = 0;
9247 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9248 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9249 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9250 GL_Color(r, g, b, a);
9251 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9255 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9257 // TODO: optimize applyfog && applycolor case
9258 // just apply fog if necessary, and tint the fog color array if necessary
9259 rsurface.passcolor4f = NULL;
9260 rsurface.passcolor4f_vertexbuffer = 0;
9261 rsurface.passcolor4f_bufferoffset = 0;
9262 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9263 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9264 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9265 GL_Color(r, g, b, a);
9269 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9272 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9273 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9274 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9275 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9276 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9277 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9278 GL_Color(r, g, b, a);
9282 static void RSurf_DrawBatch_GL11_ClampColor(void)
9287 if (!rsurface.passcolor4f)
9289 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9291 c2[0] = bound(0.0f, c1[0], 1.0f);
9292 c2[1] = bound(0.0f, c1[1], 1.0f);
9293 c2[2] = bound(0.0f, c1[2], 1.0f);
9294 c2[3] = bound(0.0f, c1[3], 1.0f);
9298 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9308 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9309 rsurface.passcolor4f_vertexbuffer = 0;
9310 rsurface.passcolor4f_bufferoffset = 0;
9311 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)
9313 f = -DotProduct(r_refdef.view.forward, n);
9315 f = f * 0.85 + 0.15; // work around so stuff won't get black
9316 f *= r_refdef.lightmapintensity;
9317 Vector4Set(c, f, f, f, 1);
9321 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9323 RSurf_DrawBatch_GL11_ApplyFakeLight();
9324 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9325 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9326 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9327 GL_Color(r, g, b, a);
9331 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9339 vec3_t ambientcolor;
9340 vec3_t diffusecolor;
9344 VectorCopy(rsurface.modellight_lightdir, lightdir);
9345 f = 0.5f * r_refdef.lightmapintensity;
9346 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9347 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9348 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9349 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9350 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9351 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9353 if (VectorLength2(diffusecolor) > 0)
9355 // q3-style directional shading
9356 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9357 rsurface.passcolor4f_vertexbuffer = 0;
9358 rsurface.passcolor4f_bufferoffset = 0;
9359 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)
9361 if ((f = DotProduct(n, lightdir)) > 0)
9362 VectorMA(ambientcolor, f, diffusecolor, c);
9364 VectorCopy(ambientcolor, c);
9371 *applycolor = false;
9375 *r = ambientcolor[0];
9376 *g = ambientcolor[1];
9377 *b = ambientcolor[2];
9378 rsurface.passcolor4f = NULL;
9379 rsurface.passcolor4f_vertexbuffer = 0;
9380 rsurface.passcolor4f_bufferoffset = 0;
9384 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9386 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9387 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9388 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9389 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9390 GL_Color(r, g, b, a);
9394 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9402 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9403 rsurface.passcolor4f_vertexbuffer = 0;
9404 rsurface.passcolor4f_bufferoffset = 0;
9406 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9408 f = 1 - RSurf_FogVertex(v);
9416 void RSurf_SetupDepthAndCulling(void)
9418 // submodels are biased to avoid z-fighting with world surfaces that they
9419 // may be exactly overlapping (avoids z-fighting artifacts on certain
9420 // doors and things in Quake maps)
9421 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9422 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9423 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9424 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9427 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9429 // transparent sky would be ridiculous
9430 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9432 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9433 skyrenderlater = true;
9434 RSurf_SetupDepthAndCulling();
9436 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9437 // skymasking on them, and Quake3 never did sky masking (unlike
9438 // software Quake and software Quake2), so disable the sky masking
9439 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9440 // and skymasking also looks very bad when noclipping outside the
9441 // level, so don't use it then either.
9442 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9444 R_Mesh_ResetTextureState();
9445 if (skyrendermasked)
9447 R_SetupShader_DepthOrShadow();
9448 // depth-only (masking)
9449 GL_ColorMask(0,0,0,0);
9450 // just to make sure that braindead drivers don't draw
9451 // anything despite that colormask...
9452 GL_BlendFunc(GL_ZERO, GL_ONE);
9453 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9454 if (rsurface.batchvertex3fbuffer)
9455 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9457 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9461 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9463 GL_BlendFunc(GL_ONE, GL_ZERO);
9464 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9465 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9466 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9469 if (skyrendermasked)
9470 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9472 R_Mesh_ResetTextureState();
9473 GL_Color(1, 1, 1, 1);
9476 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9477 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9478 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9480 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9484 // render screenspace normalmap to texture
9486 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9490 // bind lightmap texture
9492 // water/refraction/reflection/camera surfaces have to be handled specially
9493 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9495 int start, end, startplaneindex;
9496 for (start = 0;start < texturenumsurfaces;start = end)
9498 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9499 if(startplaneindex < 0)
9501 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9502 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9506 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9508 // now that we have a batch using the same planeindex, render it
9509 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9511 // render water or distortion background
9513 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));
9515 // blend surface on top
9516 GL_DepthMask(false);
9517 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9520 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9522 // render surface with reflection texture as input
9523 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9524 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));
9531 // render surface batch normally
9532 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9533 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9534 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9537 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9538 GL_AlphaTest(false);
9541 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9543 // OpenGL 1.3 path - anything not completely ancient
9544 qboolean applycolor;
9547 const texturelayer_t *layer;
9548 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);
9549 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9551 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9554 int layertexrgbscale;
9555 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9557 if (layerindex == 0)
9561 GL_AlphaTest(false);
9562 GL_DepthFunc(GL_EQUAL);
9565 GL_DepthMask(layer->depthmask && writedepth);
9566 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9567 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9569 layertexrgbscale = 4;
9570 VectorScale(layer->color, 0.25f, layercolor);
9572 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9574 layertexrgbscale = 2;
9575 VectorScale(layer->color, 0.5f, layercolor);
9579 layertexrgbscale = 1;
9580 VectorScale(layer->color, 1.0f, layercolor);
9582 layercolor[3] = layer->color[3];
9583 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9584 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9585 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9586 switch (layer->type)
9588 case TEXTURELAYERTYPE_LITTEXTURE:
9589 // single-pass lightmapped texture with 2x rgbscale
9590 R_Mesh_TexBind(0, r_texture_white);
9591 R_Mesh_TexMatrix(0, NULL);
9592 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9593 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9594 R_Mesh_TexBind(1, layer->texture);
9595 R_Mesh_TexMatrix(1, &layer->texmatrix);
9596 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9597 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9598 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9599 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9600 else if (FAKELIGHT_ENABLED)
9601 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9602 else if (rsurface.uselightmaptexture)
9603 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9605 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9607 case TEXTURELAYERTYPE_TEXTURE:
9608 // singletexture unlit texture with transparency support
9609 R_Mesh_TexBind(0, layer->texture);
9610 R_Mesh_TexMatrix(0, &layer->texmatrix);
9611 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9612 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9613 R_Mesh_TexBind(1, 0);
9614 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9615 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9617 case TEXTURELAYERTYPE_FOG:
9618 // singletexture fogging
9621 R_Mesh_TexBind(0, layer->texture);
9622 R_Mesh_TexMatrix(0, &layer->texmatrix);
9623 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9624 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9628 R_Mesh_TexBind(0, 0);
9629 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9631 R_Mesh_TexBind(1, 0);
9632 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9633 // generate a color array for the fog pass
9634 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9635 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9639 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9642 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9644 GL_DepthFunc(GL_LEQUAL);
9645 GL_AlphaTest(false);
9649 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9651 // OpenGL 1.1 - crusty old voodoo path
9654 const texturelayer_t *layer;
9655 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);
9656 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9658 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9660 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9662 if (layerindex == 0)
9666 GL_AlphaTest(false);
9667 GL_DepthFunc(GL_EQUAL);
9670 GL_DepthMask(layer->depthmask && writedepth);
9671 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9672 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9673 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9674 switch (layer->type)
9676 case TEXTURELAYERTYPE_LITTEXTURE:
9677 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9679 // two-pass lit texture with 2x rgbscale
9680 // first the lightmap pass
9681 R_Mesh_TexBind(0, r_texture_white);
9682 R_Mesh_TexMatrix(0, NULL);
9683 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9684 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9685 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9686 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9687 else if (FAKELIGHT_ENABLED)
9688 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9689 else if (rsurface.uselightmaptexture)
9690 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9692 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9693 // then apply the texture to it
9694 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9695 R_Mesh_TexBind(0, layer->texture);
9696 R_Mesh_TexMatrix(0, &layer->texmatrix);
9697 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9698 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9699 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);
9703 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9704 R_Mesh_TexBind(0, layer->texture);
9705 R_Mesh_TexMatrix(0, &layer->texmatrix);
9706 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9707 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9708 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9709 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);
9711 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);
9714 case TEXTURELAYERTYPE_TEXTURE:
9715 // singletexture unlit texture with transparency support
9716 R_Mesh_TexBind(0, layer->texture);
9717 R_Mesh_TexMatrix(0, &layer->texmatrix);
9718 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9719 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9720 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);
9722 case TEXTURELAYERTYPE_FOG:
9723 // singletexture fogging
9726 R_Mesh_TexBind(0, layer->texture);
9727 R_Mesh_TexMatrix(0, &layer->texmatrix);
9728 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9729 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9733 R_Mesh_TexBind(0, 0);
9734 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9736 // generate a color array for the fog pass
9737 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9738 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9742 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9745 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9747 GL_DepthFunc(GL_LEQUAL);
9748 GL_AlphaTest(false);
9752 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9756 r_vertexgeneric_t *batchvertex;
9759 // R_Mesh_ResetTextureState();
9760 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9762 if(rsurface.texture && rsurface.texture->currentskinframe)
9764 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9765 c[3] *= rsurface.texture->currentalpha;
9775 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9777 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9778 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9779 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9782 // brighten it up (as texture value 127 means "unlit")
9783 c[0] *= 2 * r_refdef.view.colorscale;
9784 c[1] *= 2 * r_refdef.view.colorscale;
9785 c[2] *= 2 * r_refdef.view.colorscale;
9787 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9788 c[3] *= r_wateralpha.value;
9790 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9792 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9793 GL_DepthMask(false);
9795 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9797 GL_BlendFunc(GL_ONE, GL_ONE);
9798 GL_DepthMask(false);
9800 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9802 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9803 GL_DepthMask(false);
9805 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9807 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9808 GL_DepthMask(false);
9812 GL_BlendFunc(GL_ONE, GL_ZERO);
9813 GL_DepthMask(writedepth);
9816 if (r_showsurfaces.integer == 3)
9818 rsurface.passcolor4f = NULL;
9820 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9822 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9824 rsurface.passcolor4f = NULL;
9825 rsurface.passcolor4f_vertexbuffer = 0;
9826 rsurface.passcolor4f_bufferoffset = 0;
9828 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9830 qboolean applycolor = true;
9833 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9835 r_refdef.lightmapintensity = 1;
9836 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9837 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9839 else if (FAKELIGHT_ENABLED)
9841 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9843 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9844 RSurf_DrawBatch_GL11_ApplyFakeLight();
9845 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9849 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9851 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9852 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9853 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9856 if(!rsurface.passcolor4f)
9857 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9859 RSurf_DrawBatch_GL11_ApplyAmbient();
9860 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9861 if(r_refdef.fogenabled)
9862 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9863 RSurf_DrawBatch_GL11_ClampColor();
9865 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9866 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9869 else if (!r_refdef.view.showdebug)
9871 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9872 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9873 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9875 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9876 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9878 R_Mesh_PrepareVertices_Generic_Unlock();
9881 else if (r_showsurfaces.integer == 4)
9883 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9884 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9885 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9887 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9888 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9889 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9891 R_Mesh_PrepareVertices_Generic_Unlock();
9894 else if (r_showsurfaces.integer == 2)
9897 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9898 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9899 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9901 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9902 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9903 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9904 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9905 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9906 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9907 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9909 R_Mesh_PrepareVertices_Generic_Unlock();
9910 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9914 int texturesurfaceindex;
9916 const msurface_t *surface;
9917 float surfacecolor4f[4];
9918 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9919 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9921 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9923 surface = texturesurfacelist[texturesurfaceindex];
9924 k = (int)(((size_t)surface) / sizeof(msurface_t));
9925 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9926 for (j = 0;j < surface->num_vertices;j++)
9928 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9929 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9933 R_Mesh_PrepareVertices_Generic_Unlock();
9938 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9941 RSurf_SetupDepthAndCulling();
9942 if (r_showsurfaces.integer)
9944 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9947 switch (vid.renderpath)
9949 case RENDERPATH_GL20:
9950 case RENDERPATH_D3D9:
9951 case RENDERPATH_D3D10:
9952 case RENDERPATH_D3D11:
9953 case RENDERPATH_SOFT:
9954 case RENDERPATH_GLES2:
9955 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9957 case RENDERPATH_GL13:
9958 case RENDERPATH_GLES1:
9959 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9961 case RENDERPATH_GL11:
9962 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9968 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9971 RSurf_SetupDepthAndCulling();
9972 if (r_showsurfaces.integer)
9974 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9977 switch (vid.renderpath)
9979 case RENDERPATH_GL20:
9980 case RENDERPATH_D3D9:
9981 case RENDERPATH_D3D10:
9982 case RENDERPATH_D3D11:
9983 case RENDERPATH_SOFT:
9984 case RENDERPATH_GLES2:
9985 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9987 case RENDERPATH_GL13:
9988 case RENDERPATH_GLES1:
9989 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9991 case RENDERPATH_GL11:
9992 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9998 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10001 int texturenumsurfaces, endsurface;
10002 texture_t *texture;
10003 const msurface_t *surface;
10004 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10006 // if the model is static it doesn't matter what value we give for
10007 // wantnormals and wanttangents, so this logic uses only rules applicable
10008 // to a model, knowing that they are meaningless otherwise
10009 if (ent == r_refdef.scene.worldentity)
10010 RSurf_ActiveWorldEntity();
10011 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10012 RSurf_ActiveModelEntity(ent, false, false, false);
10015 switch (vid.renderpath)
10017 case RENDERPATH_GL20:
10018 case RENDERPATH_D3D9:
10019 case RENDERPATH_D3D10:
10020 case RENDERPATH_D3D11:
10021 case RENDERPATH_SOFT:
10022 case RENDERPATH_GLES2:
10023 RSurf_ActiveModelEntity(ent, true, true, false);
10025 case RENDERPATH_GL11:
10026 case RENDERPATH_GL13:
10027 case RENDERPATH_GLES1:
10028 RSurf_ActiveModelEntity(ent, true, false, false);
10033 if (r_transparentdepthmasking.integer)
10035 qboolean setup = false;
10036 for (i = 0;i < numsurfaces;i = j)
10039 surface = rsurface.modelsurfaces + surfacelist[i];
10040 texture = surface->texture;
10041 rsurface.texture = R_GetCurrentTexture(texture);
10042 rsurface.lightmaptexture = NULL;
10043 rsurface.deluxemaptexture = NULL;
10044 rsurface.uselightmaptexture = false;
10045 // scan ahead until we find a different texture
10046 endsurface = min(i + 1024, numsurfaces);
10047 texturenumsurfaces = 0;
10048 texturesurfacelist[texturenumsurfaces++] = surface;
10049 for (;j < endsurface;j++)
10051 surface = rsurface.modelsurfaces + surfacelist[j];
10052 if (texture != surface->texture)
10054 texturesurfacelist[texturenumsurfaces++] = surface;
10056 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10058 // render the range of surfaces as depth
10062 GL_ColorMask(0,0,0,0);
10064 GL_DepthTest(true);
10065 GL_BlendFunc(GL_ONE, GL_ZERO);
10066 GL_DepthMask(true);
10067 // R_Mesh_ResetTextureState();
10068 R_SetupShader_DepthOrShadow();
10070 RSurf_SetupDepthAndCulling();
10071 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10072 if (rsurface.batchvertex3fbuffer)
10073 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10075 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10079 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10082 for (i = 0;i < numsurfaces;i = j)
10085 surface = rsurface.modelsurfaces + surfacelist[i];
10086 texture = surface->texture;
10087 rsurface.texture = R_GetCurrentTexture(texture);
10088 // scan ahead until we find a different texture
10089 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10090 texturenumsurfaces = 0;
10091 texturesurfacelist[texturenumsurfaces++] = surface;
10092 if(FAKELIGHT_ENABLED)
10094 rsurface.lightmaptexture = NULL;
10095 rsurface.deluxemaptexture = NULL;
10096 rsurface.uselightmaptexture = false;
10097 for (;j < endsurface;j++)
10099 surface = rsurface.modelsurfaces + surfacelist[j];
10100 if (texture != surface->texture)
10102 texturesurfacelist[texturenumsurfaces++] = surface;
10107 rsurface.lightmaptexture = surface->lightmaptexture;
10108 rsurface.deluxemaptexture = surface->deluxemaptexture;
10109 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10110 for (;j < endsurface;j++)
10112 surface = rsurface.modelsurfaces + surfacelist[j];
10113 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10115 texturesurfacelist[texturenumsurfaces++] = surface;
10118 // render the range of surfaces
10119 if (ent == r_refdef.scene.worldentity)
10120 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10122 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10124 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10127 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10129 // transparent surfaces get pushed off into the transparent queue
10130 int surfacelistindex;
10131 const msurface_t *surface;
10132 vec3_t tempcenter, center;
10133 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10135 surface = texturesurfacelist[surfacelistindex];
10136 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10137 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10138 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10139 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10140 if (queueentity->transparent_offset) // transparent offset
10142 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10143 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10144 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10146 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10150 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10152 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10154 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10156 RSurf_SetupDepthAndCulling();
10157 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10158 if (rsurface.batchvertex3fbuffer)
10159 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10161 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10165 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10167 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10170 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10173 if (!rsurface.texture->currentnumlayers)
10175 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10176 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10178 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10180 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10181 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10182 else if (!rsurface.texture->currentnumlayers)
10184 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10186 // in the deferred case, transparent surfaces were queued during prepass
10187 if (!r_shadow_usingdeferredprepass)
10188 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10192 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10193 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10198 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10201 texture_t *texture;
10202 R_FrameData_SetMark();
10203 // break the surface list down into batches by texture and use of lightmapping
10204 for (i = 0;i < numsurfaces;i = j)
10207 // texture is the base texture pointer, rsurface.texture is the
10208 // current frame/skin the texture is directing us to use (for example
10209 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10210 // use skin 1 instead)
10211 texture = surfacelist[i]->texture;
10212 rsurface.texture = R_GetCurrentTexture(texture);
10213 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10215 // if this texture is not the kind we want, skip ahead to the next one
10216 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10220 if(FAKELIGHT_ENABLED || depthonly || prepass)
10222 rsurface.lightmaptexture = NULL;
10223 rsurface.deluxemaptexture = NULL;
10224 rsurface.uselightmaptexture = false;
10225 // simply scan ahead until we find a different texture or lightmap state
10226 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10231 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10232 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10233 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10234 // simply scan ahead until we find a different texture or lightmap state
10235 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10238 // render the range of surfaces
10239 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10241 R_FrameData_ReturnToMark();
10244 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10248 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10251 if (!rsurface.texture->currentnumlayers)
10253 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10254 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10256 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10258 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10259 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10260 else if (!rsurface.texture->currentnumlayers)
10262 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10264 // in the deferred case, transparent surfaces were queued during prepass
10265 if (!r_shadow_usingdeferredprepass)
10266 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10270 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10271 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10276 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10279 texture_t *texture;
10280 R_FrameData_SetMark();
10281 // break the surface list down into batches by texture and use of lightmapping
10282 for (i = 0;i < numsurfaces;i = j)
10285 // texture is the base texture pointer, rsurface.texture is the
10286 // current frame/skin the texture is directing us to use (for example
10287 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10288 // use skin 1 instead)
10289 texture = surfacelist[i]->texture;
10290 rsurface.texture = R_GetCurrentTexture(texture);
10291 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10293 // if this texture is not the kind we want, skip ahead to the next one
10294 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10298 if(FAKELIGHT_ENABLED || depthonly || prepass)
10300 rsurface.lightmaptexture = NULL;
10301 rsurface.deluxemaptexture = NULL;
10302 rsurface.uselightmaptexture = false;
10303 // simply scan ahead until we find a different texture or lightmap state
10304 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10309 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10310 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10311 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10312 // simply scan ahead until we find a different texture or lightmap state
10313 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10316 // render the range of surfaces
10317 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10319 R_FrameData_ReturnToMark();
10322 float locboxvertex3f[6*4*3] =
10324 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10325 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10326 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10327 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10328 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10329 1,0,0, 0,0,0, 0,1,0, 1,1,0
10332 unsigned short locboxelements[6*2*3] =
10337 12,13,14, 12,14,15,
10338 16,17,18, 16,18,19,
10342 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10345 cl_locnode_t *loc = (cl_locnode_t *)ent;
10347 float vertex3f[6*4*3];
10349 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10350 GL_DepthMask(false);
10351 GL_DepthRange(0, 1);
10352 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10353 GL_DepthTest(true);
10354 GL_CullFace(GL_NONE);
10355 R_EntityMatrix(&identitymatrix);
10357 // R_Mesh_ResetTextureState();
10359 i = surfacelist[0];
10360 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10361 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10362 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10363 surfacelist[0] < 0 ? 0.5f : 0.125f);
10365 if (VectorCompare(loc->mins, loc->maxs))
10367 VectorSet(size, 2, 2, 2);
10368 VectorMA(loc->mins, -0.5f, size, mins);
10372 VectorCopy(loc->mins, mins);
10373 VectorSubtract(loc->maxs, loc->mins, size);
10376 for (i = 0;i < 6*4*3;)
10377 for (j = 0;j < 3;j++, i++)
10378 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10380 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10381 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10382 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10385 void R_DrawLocs(void)
10388 cl_locnode_t *loc, *nearestloc;
10390 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10391 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10393 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10394 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10398 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10400 if (decalsystem->decals)
10401 Mem_Free(decalsystem->decals);
10402 memset(decalsystem, 0, sizeof(*decalsystem));
10405 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)
10408 tridecal_t *decals;
10411 // expand or initialize the system
10412 if (decalsystem->maxdecals <= decalsystem->numdecals)
10414 decalsystem_t old = *decalsystem;
10415 qboolean useshortelements;
10416 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10417 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10418 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)));
10419 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10420 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10421 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10422 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10423 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10424 if (decalsystem->numdecals)
10425 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10427 Mem_Free(old.decals);
10428 for (i = 0;i < decalsystem->maxdecals*3;i++)
10429 decalsystem->element3i[i] = i;
10430 if (useshortelements)
10431 for (i = 0;i < decalsystem->maxdecals*3;i++)
10432 decalsystem->element3s[i] = i;
10435 // grab a decal and search for another free slot for the next one
10436 decals = decalsystem->decals;
10437 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10438 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10440 decalsystem->freedecal = i;
10441 if (decalsystem->numdecals <= i)
10442 decalsystem->numdecals = i + 1;
10444 // initialize the decal
10446 decal->triangleindex = triangleindex;
10447 decal->surfaceindex = surfaceindex;
10448 decal->decalsequence = decalsequence;
10449 decal->color4f[0][0] = c0[0];
10450 decal->color4f[0][1] = c0[1];
10451 decal->color4f[0][2] = c0[2];
10452 decal->color4f[0][3] = 1;
10453 decal->color4f[1][0] = c1[0];
10454 decal->color4f[1][1] = c1[1];
10455 decal->color4f[1][2] = c1[2];
10456 decal->color4f[1][3] = 1;
10457 decal->color4f[2][0] = c2[0];
10458 decal->color4f[2][1] = c2[1];
10459 decal->color4f[2][2] = c2[2];
10460 decal->color4f[2][3] = 1;
10461 decal->vertex3f[0][0] = v0[0];
10462 decal->vertex3f[0][1] = v0[1];
10463 decal->vertex3f[0][2] = v0[2];
10464 decal->vertex3f[1][0] = v1[0];
10465 decal->vertex3f[1][1] = v1[1];
10466 decal->vertex3f[1][2] = v1[2];
10467 decal->vertex3f[2][0] = v2[0];
10468 decal->vertex3f[2][1] = v2[1];
10469 decal->vertex3f[2][2] = v2[2];
10470 decal->texcoord2f[0][0] = t0[0];
10471 decal->texcoord2f[0][1] = t0[1];
10472 decal->texcoord2f[1][0] = t1[0];
10473 decal->texcoord2f[1][1] = t1[1];
10474 decal->texcoord2f[2][0] = t2[0];
10475 decal->texcoord2f[2][1] = t2[1];
10476 TriangleNormal(v0, v1, v2, decal->plane);
10477 VectorNormalize(decal->plane);
10478 decal->plane[3] = DotProduct(v0, decal->plane);
10481 extern cvar_t cl_decals_bias;
10482 extern cvar_t cl_decals_models;
10483 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10484 // baseparms, parms, temps
10485 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)
10490 const float *vertex3f;
10491 const float *normal3f;
10493 float points[2][9][3];
10500 e = rsurface.modelelement3i + 3*triangleindex;
10502 vertex3f = rsurface.modelvertex3f;
10503 normal3f = rsurface.modelnormal3f;
10507 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10509 index = 3*e[cornerindex];
10510 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10515 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10517 index = 3*e[cornerindex];
10518 VectorCopy(vertex3f + index, v[cornerindex]);
10523 //TriangleNormal(v[0], v[1], v[2], normal);
10524 //if (DotProduct(normal, localnormal) < 0.0f)
10526 // clip by each of the box planes formed from the projection matrix
10527 // if anything survives, we emit the decal
10528 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]);
10531 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]);
10534 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]);
10537 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]);
10540 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]);
10543 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]);
10546 // some part of the triangle survived, so we have to accept it...
10549 // dynamic always uses the original triangle
10551 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10553 index = 3*e[cornerindex];
10554 VectorCopy(vertex3f + index, v[cornerindex]);
10557 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10559 // convert vertex positions to texcoords
10560 Matrix4x4_Transform(projection, v[cornerindex], temp);
10561 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10562 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10563 // calculate distance fade from the projection origin
10564 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10565 f = bound(0.0f, f, 1.0f);
10566 c[cornerindex][0] = r * f;
10567 c[cornerindex][1] = g * f;
10568 c[cornerindex][2] = b * f;
10569 c[cornerindex][3] = 1.0f;
10570 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10573 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);
10575 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10576 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);
10578 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)
10580 matrix4x4_t projection;
10581 decalsystem_t *decalsystem;
10584 const msurface_t *surface;
10585 const msurface_t *surfaces;
10586 const int *surfacelist;
10587 const texture_t *texture;
10589 int numsurfacelist;
10590 int surfacelistindex;
10593 float localorigin[3];
10594 float localnormal[3];
10595 float localmins[3];
10596 float localmaxs[3];
10599 float planes[6][4];
10602 int bih_triangles_count;
10603 int bih_triangles[256];
10604 int bih_surfaces[256];
10606 decalsystem = &ent->decalsystem;
10607 model = ent->model;
10608 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10610 R_DecalSystem_Reset(&ent->decalsystem);
10614 if (!model->brush.data_leafs && !cl_decals_models.integer)
10616 if (decalsystem->model)
10617 R_DecalSystem_Reset(decalsystem);
10621 if (decalsystem->model != model)
10622 R_DecalSystem_Reset(decalsystem);
10623 decalsystem->model = model;
10625 RSurf_ActiveModelEntity(ent, true, false, false);
10627 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10628 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10629 VectorNormalize(localnormal);
10630 localsize = worldsize*rsurface.inversematrixscale;
10631 localmins[0] = localorigin[0] - localsize;
10632 localmins[1] = localorigin[1] - localsize;
10633 localmins[2] = localorigin[2] - localsize;
10634 localmaxs[0] = localorigin[0] + localsize;
10635 localmaxs[1] = localorigin[1] + localsize;
10636 localmaxs[2] = localorigin[2] + localsize;
10638 //VectorCopy(localnormal, planes[4]);
10639 //VectorVectors(planes[4], planes[2], planes[0]);
10640 AnglesFromVectors(angles, localnormal, NULL, false);
10641 AngleVectors(angles, planes[0], planes[2], planes[4]);
10642 VectorNegate(planes[0], planes[1]);
10643 VectorNegate(planes[2], planes[3]);
10644 VectorNegate(planes[4], planes[5]);
10645 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10646 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10647 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10648 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10649 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10650 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10655 matrix4x4_t forwardprojection;
10656 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10657 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10662 float projectionvector[4][3];
10663 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10664 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10665 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10666 projectionvector[0][0] = planes[0][0] * ilocalsize;
10667 projectionvector[0][1] = planes[1][0] * ilocalsize;
10668 projectionvector[0][2] = planes[2][0] * ilocalsize;
10669 projectionvector[1][0] = planes[0][1] * ilocalsize;
10670 projectionvector[1][1] = planes[1][1] * ilocalsize;
10671 projectionvector[1][2] = planes[2][1] * ilocalsize;
10672 projectionvector[2][0] = planes[0][2] * ilocalsize;
10673 projectionvector[2][1] = planes[1][2] * ilocalsize;
10674 projectionvector[2][2] = planes[2][2] * ilocalsize;
10675 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10676 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10677 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10678 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10682 dynamic = model->surfmesh.isanimated;
10683 numsurfacelist = model->nummodelsurfaces;
10684 surfacelist = model->sortedmodelsurfaces;
10685 surfaces = model->data_surfaces;
10688 bih_triangles_count = -1;
10691 if(model->render_bih.numleafs)
10692 bih = &model->render_bih;
10693 else if(model->collision_bih.numleafs)
10694 bih = &model->collision_bih;
10697 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10698 if(bih_triangles_count == 0)
10700 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10702 if(bih_triangles_count > 0)
10704 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10706 surfaceindex = bih_surfaces[triangleindex];
10707 surface = surfaces + surfaceindex;
10708 texture = surface->texture;
10709 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10711 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10713 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10718 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10720 surfaceindex = surfacelist[surfacelistindex];
10721 surface = surfaces + surfaceindex;
10722 // check cull box first because it rejects more than any other check
10723 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10725 // skip transparent surfaces
10726 texture = surface->texture;
10727 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10729 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10731 numtriangles = surface->num_triangles;
10732 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10733 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10738 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10739 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)
10741 int renderentityindex;
10742 float worldmins[3];
10743 float worldmaxs[3];
10744 entity_render_t *ent;
10746 if (!cl_decals_newsystem.integer)
10749 worldmins[0] = worldorigin[0] - worldsize;
10750 worldmins[1] = worldorigin[1] - worldsize;
10751 worldmins[2] = worldorigin[2] - worldsize;
10752 worldmaxs[0] = worldorigin[0] + worldsize;
10753 worldmaxs[1] = worldorigin[1] + worldsize;
10754 worldmaxs[2] = worldorigin[2] + worldsize;
10756 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10758 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10760 ent = r_refdef.scene.entities[renderentityindex];
10761 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10764 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10768 typedef struct r_decalsystem_splatqueue_s
10770 vec3_t worldorigin;
10771 vec3_t worldnormal;
10777 r_decalsystem_splatqueue_t;
10779 int r_decalsystem_numqueued = 0;
10780 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10782 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)
10784 r_decalsystem_splatqueue_t *queue;
10786 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10789 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10790 VectorCopy(worldorigin, queue->worldorigin);
10791 VectorCopy(worldnormal, queue->worldnormal);
10792 Vector4Set(queue->color, r, g, b, a);
10793 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10794 queue->worldsize = worldsize;
10795 queue->decalsequence = cl.decalsequence++;
10798 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10801 r_decalsystem_splatqueue_t *queue;
10803 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10804 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);
10805 r_decalsystem_numqueued = 0;
10808 extern cvar_t cl_decals_max;
10809 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10812 decalsystem_t *decalsystem = &ent->decalsystem;
10819 if (!decalsystem->numdecals)
10822 if (r_showsurfaces.integer)
10825 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10827 R_DecalSystem_Reset(decalsystem);
10831 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10832 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10834 if (decalsystem->lastupdatetime)
10835 frametime = (cl.time - decalsystem->lastupdatetime);
10838 decalsystem->lastupdatetime = cl.time;
10839 decal = decalsystem->decals;
10840 numdecals = decalsystem->numdecals;
10842 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10844 if (decal->color4f[0][3])
10846 decal->lived += frametime;
10847 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10849 memset(decal, 0, sizeof(*decal));
10850 if (decalsystem->freedecal > i)
10851 decalsystem->freedecal = i;
10855 decal = decalsystem->decals;
10856 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10859 // collapse the array by shuffling the tail decals into the gaps
10862 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10863 decalsystem->freedecal++;
10864 if (decalsystem->freedecal == numdecals)
10866 decal[decalsystem->freedecal] = decal[--numdecals];
10869 decalsystem->numdecals = numdecals;
10871 if (numdecals <= 0)
10873 // if there are no decals left, reset decalsystem
10874 R_DecalSystem_Reset(decalsystem);
10878 extern skinframe_t *decalskinframe;
10879 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10882 decalsystem_t *decalsystem = &ent->decalsystem;
10891 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10894 numdecals = decalsystem->numdecals;
10898 if (r_showsurfaces.integer)
10901 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10903 R_DecalSystem_Reset(decalsystem);
10907 // if the model is static it doesn't matter what value we give for
10908 // wantnormals and wanttangents, so this logic uses only rules applicable
10909 // to a model, knowing that they are meaningless otherwise
10910 if (ent == r_refdef.scene.worldentity)
10911 RSurf_ActiveWorldEntity();
10913 RSurf_ActiveModelEntity(ent, false, false, false);
10915 decalsystem->lastupdatetime = cl.time;
10916 decal = decalsystem->decals;
10918 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10920 // update vertex positions for animated models
10921 v3f = decalsystem->vertex3f;
10922 c4f = decalsystem->color4f;
10923 t2f = decalsystem->texcoord2f;
10924 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10926 if (!decal->color4f[0][3])
10929 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10933 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10936 // update color values for fading decals
10937 if (decal->lived >= cl_decals_time.value)
10938 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10942 c4f[ 0] = decal->color4f[0][0] * alpha;
10943 c4f[ 1] = decal->color4f[0][1] * alpha;
10944 c4f[ 2] = decal->color4f[0][2] * alpha;
10946 c4f[ 4] = decal->color4f[1][0] * alpha;
10947 c4f[ 5] = decal->color4f[1][1] * alpha;
10948 c4f[ 6] = decal->color4f[1][2] * alpha;
10950 c4f[ 8] = decal->color4f[2][0] * alpha;
10951 c4f[ 9] = decal->color4f[2][1] * alpha;
10952 c4f[10] = decal->color4f[2][2] * alpha;
10955 t2f[0] = decal->texcoord2f[0][0];
10956 t2f[1] = decal->texcoord2f[0][1];
10957 t2f[2] = decal->texcoord2f[1][0];
10958 t2f[3] = decal->texcoord2f[1][1];
10959 t2f[4] = decal->texcoord2f[2][0];
10960 t2f[5] = decal->texcoord2f[2][1];
10962 // update vertex positions for animated models
10963 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10965 e = rsurface.modelelement3i + 3*decal->triangleindex;
10966 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10967 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10968 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10972 VectorCopy(decal->vertex3f[0], v3f);
10973 VectorCopy(decal->vertex3f[1], v3f + 3);
10974 VectorCopy(decal->vertex3f[2], v3f + 6);
10977 if (r_refdef.fogenabled)
10979 alpha = RSurf_FogVertex(v3f);
10980 VectorScale(c4f, alpha, c4f);
10981 alpha = RSurf_FogVertex(v3f + 3);
10982 VectorScale(c4f + 4, alpha, c4f + 4);
10983 alpha = RSurf_FogVertex(v3f + 6);
10984 VectorScale(c4f + 8, alpha, c4f + 8);
10995 r_refdef.stats.drawndecals += numtris;
10997 // now render the decals all at once
10998 // (this assumes they all use one particle font texture!)
10999 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);
11000 // R_Mesh_ResetTextureState();
11001 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11002 GL_DepthMask(false);
11003 GL_DepthRange(0, 1);
11004 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11005 GL_DepthTest(true);
11006 GL_CullFace(GL_NONE);
11007 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11008 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11009 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11013 static void R_DrawModelDecals(void)
11017 // fade faster when there are too many decals
11018 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11019 for (i = 0;i < r_refdef.scene.numentities;i++)
11020 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11022 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11023 for (i = 0;i < r_refdef.scene.numentities;i++)
11024 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11025 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11027 R_DecalSystem_ApplySplatEntitiesQueue();
11029 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11030 for (i = 0;i < r_refdef.scene.numentities;i++)
11031 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11033 r_refdef.stats.totaldecals += numdecals;
11035 if (r_showsurfaces.integer)
11038 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11040 for (i = 0;i < r_refdef.scene.numentities;i++)
11042 if (!r_refdef.viewcache.entityvisible[i])
11044 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11045 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11049 extern cvar_t mod_collision_bih;
11050 void R_DrawDebugModel(void)
11052 entity_render_t *ent = rsurface.entity;
11053 int i, j, k, l, flagsmask;
11054 const msurface_t *surface;
11055 dp_model_t *model = ent->model;
11058 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11061 if (r_showoverdraw.value > 0)
11063 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11064 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11065 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11066 GL_DepthTest(false);
11067 GL_DepthMask(false);
11068 GL_DepthRange(0, 1);
11069 GL_BlendFunc(GL_ONE, GL_ONE);
11070 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11072 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11074 rsurface.texture = R_GetCurrentTexture(surface->texture);
11075 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11077 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11078 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11079 if (!rsurface.texture->currentlayers->depthmask)
11080 GL_Color(c, 0, 0, 1.0f);
11081 else if (ent == r_refdef.scene.worldentity)
11082 GL_Color(c, c, c, 1.0f);
11084 GL_Color(0, c, 0, 1.0f);
11085 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11089 rsurface.texture = NULL;
11092 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11094 // R_Mesh_ResetTextureState();
11095 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11096 GL_DepthRange(0, 1);
11097 GL_DepthTest(!r_showdisabledepthtest.integer);
11098 GL_DepthMask(false);
11099 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11101 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11105 qboolean cullbox = ent == r_refdef.scene.worldentity;
11106 const q3mbrush_t *brush;
11107 const bih_t *bih = &model->collision_bih;
11108 const bih_leaf_t *bihleaf;
11109 float vertex3f[3][3];
11110 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11112 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11114 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11116 switch (bihleaf->type)
11119 brush = model->brush.data_brushes + bihleaf->itemindex;
11120 if (brush->colbrushf && brush->colbrushf->numtriangles)
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(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11124 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11127 case BIH_COLLISIONTRIANGLE:
11128 triangleindex = bihleaf->itemindex;
11129 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11130 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11131 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11132 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);
11133 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11134 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11136 case BIH_RENDERTRIANGLE:
11137 triangleindex = bihleaf->itemindex;
11138 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11139 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11140 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11141 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);
11142 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11143 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11149 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11151 if (r_showtris.integer && qglPolygonMode)
11153 if (r_showdisabledepthtest.integer)
11155 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11156 GL_DepthMask(false);
11160 GL_BlendFunc(GL_ONE, GL_ZERO);
11161 GL_DepthMask(true);
11163 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11164 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11166 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11168 rsurface.texture = R_GetCurrentTexture(surface->texture);
11169 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11171 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11172 if (!rsurface.texture->currentlayers->depthmask)
11173 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11174 else if (ent == r_refdef.scene.worldentity)
11175 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11177 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11178 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11182 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11183 rsurface.texture = NULL;
11186 if (r_shownormals.value != 0 && qglBegin)
11188 if (r_showdisabledepthtest.integer)
11190 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11191 GL_DepthMask(false);
11195 GL_BlendFunc(GL_ONE, GL_ZERO);
11196 GL_DepthMask(true);
11198 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11200 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11202 rsurface.texture = R_GetCurrentTexture(surface->texture);
11203 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11205 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11206 qglBegin(GL_LINES);
11207 if (r_shownormals.value < 0)
11209 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11211 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11212 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11213 qglVertex3f(v[0], v[1], v[2]);
11214 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11215 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11216 qglVertex3f(v[0], v[1], v[2]);
11219 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11221 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11223 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11224 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11225 qglVertex3f(v[0], v[1], v[2]);
11226 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11227 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11228 qglVertex3f(v[0], v[1], v[2]);
11230 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11232 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11233 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11234 qglVertex3f(v[0], v[1], v[2]);
11235 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11236 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11237 qglVertex3f(v[0], v[1], v[2]);
11239 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11241 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11242 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11243 qglVertex3f(v[0], v[1], v[2]);
11244 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11245 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11246 qglVertex3f(v[0], v[1], v[2]);
11253 rsurface.texture = NULL;
11257 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11258 int r_maxsurfacelist = 0;
11259 const msurface_t **r_surfacelist = NULL;
11260 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11262 int i, j, endj, flagsmask;
11263 dp_model_t *model = r_refdef.scene.worldmodel;
11264 msurface_t *surfaces;
11265 unsigned char *update;
11266 int numsurfacelist = 0;
11270 if (r_maxsurfacelist < model->num_surfaces)
11272 r_maxsurfacelist = model->num_surfaces;
11274 Mem_Free((msurface_t**)r_surfacelist);
11275 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11278 RSurf_ActiveWorldEntity();
11280 surfaces = model->data_surfaces;
11281 update = model->brushq1.lightmapupdateflags;
11283 // update light styles on this submodel
11284 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11286 model_brush_lightstyleinfo_t *style;
11287 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11289 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11291 int *list = style->surfacelist;
11292 style->value = r_refdef.scene.lightstylevalue[style->style];
11293 for (j = 0;j < style->numsurfaces;j++)
11294 update[list[j]] = true;
11299 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11303 R_DrawDebugModel();
11304 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11308 rsurface.lightmaptexture = NULL;
11309 rsurface.deluxemaptexture = NULL;
11310 rsurface.uselightmaptexture = false;
11311 rsurface.texture = NULL;
11312 rsurface.rtlight = NULL;
11313 numsurfacelist = 0;
11314 // add visible surfaces to draw list
11315 for (i = 0;i < model->nummodelsurfaces;i++)
11317 j = model->sortedmodelsurfaces[i];
11318 if (r_refdef.viewcache.world_surfacevisible[j])
11319 r_surfacelist[numsurfacelist++] = surfaces + j;
11321 // update lightmaps if needed
11322 if (model->brushq1.firstrender)
11324 model->brushq1.firstrender = false;
11325 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11327 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11331 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11332 if (r_refdef.viewcache.world_surfacevisible[j])
11334 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11336 // don't do anything if there were no surfaces
11337 if (!numsurfacelist)
11339 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11342 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11344 // add to stats if desired
11345 if (r_speeds.integer && !skysurfaces && !depthonly)
11347 r_refdef.stats.world_surfaces += numsurfacelist;
11348 for (j = 0;j < numsurfacelist;j++)
11349 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11352 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11355 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11357 int i, j, endj, flagsmask;
11358 dp_model_t *model = ent->model;
11359 msurface_t *surfaces;
11360 unsigned char *update;
11361 int numsurfacelist = 0;
11365 if (r_maxsurfacelist < model->num_surfaces)
11367 r_maxsurfacelist = model->num_surfaces;
11369 Mem_Free((msurface_t **)r_surfacelist);
11370 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11373 // if the model is static it doesn't matter what value we give for
11374 // wantnormals and wanttangents, so this logic uses only rules applicable
11375 // to a model, knowing that they are meaningless otherwise
11376 if (ent == r_refdef.scene.worldentity)
11377 RSurf_ActiveWorldEntity();
11378 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11379 RSurf_ActiveModelEntity(ent, false, false, false);
11381 RSurf_ActiveModelEntity(ent, true, true, true);
11382 else if (depthonly)
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, model->wantnormals, model->wanttangents, false);
11394 case RENDERPATH_GL11:
11395 case RENDERPATH_GL13:
11396 case RENDERPATH_GLES1:
11397 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11403 switch (vid.renderpath)
11405 case RENDERPATH_GL20:
11406 case RENDERPATH_D3D9:
11407 case RENDERPATH_D3D10:
11408 case RENDERPATH_D3D11:
11409 case RENDERPATH_SOFT:
11410 case RENDERPATH_GLES2:
11411 RSurf_ActiveModelEntity(ent, true, true, false);
11413 case RENDERPATH_GL11:
11414 case RENDERPATH_GL13:
11415 case RENDERPATH_GLES1:
11416 RSurf_ActiveModelEntity(ent, true, false, false);
11421 surfaces = model->data_surfaces;
11422 update = model->brushq1.lightmapupdateflags;
11424 // update light styles
11425 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11427 model_brush_lightstyleinfo_t *style;
11428 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11430 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11432 int *list = style->surfacelist;
11433 style->value = r_refdef.scene.lightstylevalue[style->style];
11434 for (j = 0;j < style->numsurfaces;j++)
11435 update[list[j]] = true;
11440 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11444 R_DrawDebugModel();
11445 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11449 rsurface.lightmaptexture = NULL;
11450 rsurface.deluxemaptexture = NULL;
11451 rsurface.uselightmaptexture = false;
11452 rsurface.texture = NULL;
11453 rsurface.rtlight = NULL;
11454 numsurfacelist = 0;
11455 // add visible surfaces to draw list
11456 for (i = 0;i < model->nummodelsurfaces;i++)
11457 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11458 // don't do anything if there were no surfaces
11459 if (!numsurfacelist)
11461 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11464 // update lightmaps if needed
11468 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11473 R_BuildLightMap(ent, surfaces + j);
11478 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11480 R_BuildLightMap(ent, surfaces + j);
11481 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11483 // add to stats if desired
11484 if (r_speeds.integer && !skysurfaces && !depthonly)
11486 r_refdef.stats.entities_surfaces += numsurfacelist;
11487 for (j = 0;j < numsurfacelist;j++)
11488 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11491 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11494 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11496 static texture_t texture;
11497 static msurface_t surface;
11498 const msurface_t *surfacelist = &surface;
11500 // fake enough texture and surface state to render this geometry
11502 texture.update_lastrenderframe = -1; // regenerate this texture
11503 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11504 texture.currentskinframe = skinframe;
11505 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11506 texture.offsetmapping = OFFSETMAPPING_OFF;
11507 texture.offsetscale = 1;
11508 texture.specularscalemod = 1;
11509 texture.specularpowermod = 1;
11511 surface.texture = &texture;
11512 surface.num_triangles = numtriangles;
11513 surface.num_firsttriangle = firsttriangle;
11514 surface.num_vertices = numvertices;
11515 surface.num_firstvertex = firstvertex;
11518 rsurface.texture = R_GetCurrentTexture(surface.texture);
11519 rsurface.lightmaptexture = NULL;
11520 rsurface.deluxemaptexture = NULL;
11521 rsurface.uselightmaptexture = false;
11522 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11525 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)
11527 static msurface_t surface;
11528 const msurface_t *surfacelist = &surface;
11530 // fake enough texture and surface state to render this geometry
11531 surface.texture = texture;
11532 surface.num_triangles = numtriangles;
11533 surface.num_firsttriangle = firsttriangle;
11534 surface.num_vertices = numvertices;
11535 surface.num_firstvertex = firstvertex;
11538 rsurface.texture = R_GetCurrentTexture(surface.texture);
11539 rsurface.lightmaptexture = NULL;
11540 rsurface.deluxemaptexture = NULL;
11541 rsurface.uselightmaptexture = false;
11542 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);