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_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
76 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
77 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)"};
78 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
79 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
80 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"};
81 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"};
82 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
83 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"};
84 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"};
85 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"};
86 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
87 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
88 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
89 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
90 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
91 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
92 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
93 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)"};
94 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)"};
95 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
96 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
97 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
98 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
101 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
102 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
105 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
106 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
107 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."};
108 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
109 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
110 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
111 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."};
112 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
113 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
114 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
115 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
116 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"};
117 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"};
118 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
119 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
121 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
122 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
123 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"};
124 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
125 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
128 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
129 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
130 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
131 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
132 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
133 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
134 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136 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)"};
137 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"};
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143 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"};
144 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"};
145 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
146 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
147 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"};
148 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)"};
149 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)"};
150 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152 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)"};
153 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
154 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)"};
155 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
156 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)"};
157 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)"};
158 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
159 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
160 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)"};
161 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)"};
162 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)"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
169 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)"};
170 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
171 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"};
172 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
173 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
174 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
177 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
178 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
179 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
181 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
182 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
183 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
184 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
185 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
186 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
187 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
189 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
190 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
191 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
192 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)"};
193 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
194 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
195 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
196 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
198 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
200 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"};
202 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"};
204 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
206 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
207 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"};
208 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
209 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
210 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
211 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
212 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)"};
213 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
214 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
216 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
217 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"};
219 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."};
221 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)"};
223 extern cvar_t v_glslgamma;
225 extern qboolean v_flipped_state;
227 static struct r_bloomstate_s
232 int bloomwidth, bloomheight;
234 textype_t texturetype;
235 int viewfbo; // used to check if r_viewfbo cvar has changed
237 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
238 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
239 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
241 int screentexturewidth, screentextureheight;
242 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
244 int bloomtexturewidth, bloomtextureheight;
245 rtexture_t *texture_bloom;
247 // arrays for rendering the screen passes
248 float screentexcoord2f[8];
249 float bloomtexcoord2f[8];
250 float offsettexcoord2f[8];
252 r_viewport_t viewport;
256 r_waterstate_t r_waterstate;
258 /// shadow volume bsp struct with automatically growing nodes buffer
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
283 int r_texture_numcubemaps;
284 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
290 typedef struct r_qwskincache_s
292 char name[MAX_QPATH];
293 skinframe_t *skinframe;
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
310 const float r_d3dscreenvertex3f[12] =
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
321 for (i = 0;i < verts;i++)
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
335 for (i = 0;i < verts;i++)
345 // FIXME: move this to client?
348 if (gamemode == GAME_NEHAHRA)
350 Cvar_Set("gl_fogenable", "0");
351 Cvar_Set("gl_fogdensity", "0.2");
352 Cvar_Set("gl_fogred", "0.3");
353 Cvar_Set("gl_foggreen", "0.3");
354 Cvar_Set("gl_fogblue", "0.3");
356 r_refdef.fog_density = 0;
357 r_refdef.fog_red = 0;
358 r_refdef.fog_green = 0;
359 r_refdef.fog_blue = 0;
360 r_refdef.fog_alpha = 1;
361 r_refdef.fog_start = 0;
362 r_refdef.fog_end = 16384;
363 r_refdef.fog_height = 1<<30;
364 r_refdef.fog_fadedepth = 128;
365 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
368 static void R_BuildBlankTextures(void)
370 unsigned char data[4];
371 data[2] = 128; // normal X
372 data[1] = 128; // normal Y
373 data[0] = 255; // normal Z
374 data[3] = 128; // height
375 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 static void R_BuildNoTexture(void)
396 unsigned char pix[16][16][4];
397 // this makes a light grey/dark grey checkerboard texture
398 for (y = 0;y < 16;y++)
400 for (x = 0;x < 16;x++)
402 if ((y < 8) ^ (x < 8))
418 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
421 static void R_BuildWhiteCube(void)
423 unsigned char data[6*1*1*4];
424 memset(data, 255, sizeof(data));
425 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
428 static void R_BuildNormalizationCube(void)
432 vec_t s, t, intensity;
435 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436 for (side = 0;side < 6;side++)
438 for (y = 0;y < NORMSIZE;y++)
440 for (x = 0;x < NORMSIZE;x++)
442 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
478 intensity = 127.0f / sqrt(DotProduct(v, v));
479 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482 data[((side*64+y)*64+x)*4+3] = 255;
486 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
490 static void R_BuildFogTexture(void)
494 unsigned char data1[FOGWIDTH][4];
495 //unsigned char data2[FOGWIDTH][4];
498 r_refdef.fogmasktable_start = r_refdef.fog_start;
499 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500 r_refdef.fogmasktable_range = r_refdef.fogrange;
501 r_refdef.fogmasktable_density = r_refdef.fog_density;
503 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506 d = (x * r - r_refdef.fogmasktable_start);
507 if(developer_extra.integer)
508 Con_DPrintf("%f ", d);
510 if (r_fog_exp2.integer)
511 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514 if(developer_extra.integer)
515 Con_DPrintf(" : %f ", alpha);
516 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517 if(developer_extra.integer)
518 Con_DPrintf(" = %f\n", alpha);
519 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
522 for (x = 0;x < FOGWIDTH;x++)
524 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529 //data2[x][0] = 255 - b;
530 //data2[x][1] = 255 - b;
531 //data2[x][2] = 255 - b;
534 if (r_texture_fogattenuation)
536 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
546 static void R_BuildFogHeightTexture(void)
548 unsigned char *inpixels;
556 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557 if (r_refdef.fogheighttexturename[0])
558 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
561 r_refdef.fog_height_tablesize = 0;
562 if (r_texture_fogheighttexture)
563 R_FreeTexture(r_texture_fogheighttexture);
564 r_texture_fogheighttexture = NULL;
565 if (r_refdef.fog_height_table2d)
566 Mem_Free(r_refdef.fog_height_table2d);
567 r_refdef.fog_height_table2d = NULL;
568 if (r_refdef.fog_height_table1d)
569 Mem_Free(r_refdef.fog_height_table1d);
570 r_refdef.fog_height_table1d = NULL;
574 r_refdef.fog_height_tablesize = size;
575 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579 // LordHavoc: now the magic - what is that table2d for? it is a cooked
580 // average fog color table accounting for every fog layer between a point
581 // and the camera. (Note: attenuation is handled separately!)
582 for (y = 0;y < size;y++)
584 for (x = 0;x < size;x++)
590 for (j = x;j <= y;j++)
592 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
598 for (j = x;j >= y;j--)
600 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
611 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
614 //=======================================================================================================================================================
616 static const char *builtinshaderstring =
617 #include "shader_glsl.h"
620 const char *builtinhlslshaderstring =
621 #include "shader_hlsl.h"
624 char *glslshaderstring = NULL;
625 char *hlslshaderstring = NULL;
627 //=======================================================================================================================================================
629 typedef struct shaderpermutationinfo_s
634 shaderpermutationinfo_t;
636 typedef struct shadermodeinfo_s
638 const char *vertexfilename;
639 const char *geometryfilename;
640 const char *fragmentfilename;
646 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
647 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
649 {"#define USEDIFFUSE\n", " diffuse"},
650 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
651 {"#define USEVIEWTINT\n", " viewtint"},
652 {"#define USECOLORMAPPING\n", " colormapping"},
653 {"#define USESATURATION\n", " saturation"},
654 {"#define USEFOGINSIDE\n", " foginside"},
655 {"#define USEFOGOUTSIDE\n", " fogoutside"},
656 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
657 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
658 {"#define USEGAMMARAMPS\n", " gammaramps"},
659 {"#define USECUBEFILTER\n", " cubefilter"},
660 {"#define USEGLOW\n", " glow"},
661 {"#define USEBLOOM\n", " bloom"},
662 {"#define USESPECULAR\n", " specular"},
663 {"#define USEPOSTPROCESSING\n", " postprocessing"},
664 {"#define USEREFLECTION\n", " reflection"},
665 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
667 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
668 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
669 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
670 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
671 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
672 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674 {"#define USEALPHAKILL\n", " alphakill"},
675 {"#define USEREFLECTCUBE\n", " reflectcube"},
676 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677 {"#define USEBOUNCEGRID\n", " bouncegrid"},
678 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
726 struct r_glsl_permutation_s *hashnext;
728 unsigned int permutation;
730 /// indicates if we have tried compiling this permutation already
732 /// 0 if compilation failed
734 // texture units assigned to each detected uniform
735 int tex_Texture_First;
736 int tex_Texture_Second;
737 int tex_Texture_GammaRamps;
738 int tex_Texture_Normal;
739 int tex_Texture_Color;
740 int tex_Texture_Gloss;
741 int tex_Texture_Glow;
742 int tex_Texture_SecondaryNormal;
743 int tex_Texture_SecondaryColor;
744 int tex_Texture_SecondaryGloss;
745 int tex_Texture_SecondaryGlow;
746 int tex_Texture_Pants;
747 int tex_Texture_Shirt;
748 int tex_Texture_FogHeightTexture;
749 int tex_Texture_FogMask;
750 int tex_Texture_Lightmap;
751 int tex_Texture_Deluxemap;
752 int tex_Texture_Attenuation;
753 int tex_Texture_Cube;
754 int tex_Texture_Refraction;
755 int tex_Texture_Reflection;
756 int tex_Texture_ShadowMap2D;
757 int tex_Texture_CubeProjection;
758 int tex_Texture_ScreenDepth;
759 int tex_Texture_ScreenNormalMap;
760 int tex_Texture_ScreenDiffuse;
761 int tex_Texture_ScreenSpecular;
762 int tex_Texture_ReflectMask;
763 int tex_Texture_ReflectCube;
764 int tex_Texture_BounceGrid;
765 /// locations of detected uniforms in program object, or -1 if not found
766 int loc_Texture_First;
767 int loc_Texture_Second;
768 int loc_Texture_GammaRamps;
769 int loc_Texture_Normal;
770 int loc_Texture_Color;
771 int loc_Texture_Gloss;
772 int loc_Texture_Glow;
773 int loc_Texture_SecondaryNormal;
774 int loc_Texture_SecondaryColor;
775 int loc_Texture_SecondaryGloss;
776 int loc_Texture_SecondaryGlow;
777 int loc_Texture_Pants;
778 int loc_Texture_Shirt;
779 int loc_Texture_FogHeightTexture;
780 int loc_Texture_FogMask;
781 int loc_Texture_Lightmap;
782 int loc_Texture_Deluxemap;
783 int loc_Texture_Attenuation;
784 int loc_Texture_Cube;
785 int loc_Texture_Refraction;
786 int loc_Texture_Reflection;
787 int loc_Texture_ShadowMap2D;
788 int loc_Texture_CubeProjection;
789 int loc_Texture_ScreenDepth;
790 int loc_Texture_ScreenNormalMap;
791 int loc_Texture_ScreenDiffuse;
792 int loc_Texture_ScreenSpecular;
793 int loc_Texture_ReflectMask;
794 int loc_Texture_ReflectCube;
795 int loc_Texture_BounceGrid;
797 int loc_BloomBlur_Parameters;
799 int loc_Color_Ambient;
800 int loc_Color_Diffuse;
801 int loc_Color_Specular;
805 int loc_DeferredColor_Ambient;
806 int loc_DeferredColor_Diffuse;
807 int loc_DeferredColor_Specular;
808 int loc_DeferredMod_Diffuse;
809 int loc_DeferredMod_Specular;
810 int loc_DistortScaleRefractReflect;
813 int loc_FogHeightFade;
815 int loc_FogPlaneViewDist;
816 int loc_FogRangeRecip;
819 int loc_LightPosition;
820 int loc_OffsetMapping_ScaleSteps;
822 int loc_ReflectColor;
823 int loc_ReflectFactor;
824 int loc_ReflectOffset;
825 int loc_RefractColor;
827 int loc_ScreenCenterRefractReflect;
828 int loc_ScreenScaleRefractReflect;
829 int loc_ScreenToDepth;
830 int loc_ShadowMap_Parameters;
831 int loc_ShadowMap_TextureScale;
832 int loc_SpecularPower;
837 int loc_ViewTintColor;
839 int loc_ModelToLight;
841 int loc_BackgroundTexMatrix;
842 int loc_ModelViewProjectionMatrix;
843 int loc_ModelViewMatrix;
844 int loc_PixelToScreenTexCoord;
845 int loc_ModelToReflectCube;
846 int loc_ShadowMapMatrix;
847 int loc_BloomColorSubtract;
848 int loc_NormalmapScrollBlend;
849 int loc_BounceGridMatrix;
850 int loc_BounceGridIntensity;
852 r_glsl_permutation_t;
854 #define SHADERPERMUTATION_HASHSIZE 256
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
861 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
867 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
869 #define SHADERSTATICPARMS_COUNT 7
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
878 static int r_compileshader_staticparms_save[1];
879 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
883 if (r_glsl_saturation_redcompensate.integer)
884 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885 if (r_glsl_vertextextureblend_usebothalphas.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887 if (r_shadow_glossexact.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889 if (r_glsl_postprocess.integer)
891 if (r_glsl_postprocess_uservec1_enable.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893 if (r_glsl_postprocess_uservec2_enable.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895 if (r_glsl_postprocess_uservec3_enable.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897 if (r_glsl_postprocess_uservec4_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
900 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 shaderstaticparms_count = 0;
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
931 //unsigned int hashdepth = 0;
932 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933 r_glsl_permutation_t *p;
934 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
936 if (p->mode == mode && p->permutation == permutation)
938 //if (hashdepth > 10)
939 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
944 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
946 p->permutation = permutation;
947 p->hashnext = r_glsl_permutationhash[mode][hashindex];
948 r_glsl_permutationhash[mode][hashindex] = p;
949 //if (hashdepth > 10)
950 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
957 if (!filename || !filename[0])
959 if (!strcmp(filename, "glsl/default.glsl"))
961 if (!glslshaderstring)
963 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964 if (glslshaderstring)
965 Con_DPrintf("Loading shaders from file %s...\n", filename);
967 glslshaderstring = (char *)builtinshaderstring;
969 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
973 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
976 if (printfromdisknotice)
977 Con_DPrintf("from disk %s... ", filename);
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
987 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988 char *vertexstring, *geometrystring, *fragmentstring;
989 char permutationname[256];
990 int vertstrings_count = 0;
991 int geomstrings_count = 0;
992 int fragstrings_count = 0;
993 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002 permutationname[0] = 0;
1003 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1007 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1009 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010 if(vid.support.gl20shaders130)
1012 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1020 // the first pretext is which type of shader to compile as
1021 // (later these will all be bound together as a program object)
1022 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1026 // the second pretext is the mode (for example a light source)
1027 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1032 // now add all the permutation pretexts
1033 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1035 if (permutation & (1<<i))
1037 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1044 // keep line numbers correct
1045 vertstrings_list[vertstrings_count++] = "\n";
1046 geomstrings_list[geomstrings_count++] = "\n";
1047 fragstrings_list[fragstrings_count++] = "\n";
1052 R_CompileShader_AddStaticParms(mode, permutation);
1053 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054 vertstrings_count += shaderstaticparms_count;
1055 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056 geomstrings_count += shaderstaticparms_count;
1057 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058 fragstrings_count += shaderstaticparms_count;
1060 // now append the shader text itself
1061 vertstrings_list[vertstrings_count++] = vertexstring;
1062 geomstrings_list[geomstrings_count++] = geometrystring;
1063 fragstrings_list[fragstrings_count++] = fragmentstring;
1065 // if any sources were NULL, clear the respective list
1067 vertstrings_count = 0;
1068 if (!geometrystring)
1069 geomstrings_count = 0;
1070 if (!fragmentstring)
1071 fragstrings_count = 0;
1073 // compile the shader program
1074 if (vertstrings_count + geomstrings_count + fragstrings_count)
1075 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1079 qglUseProgram(p->program);CHECKGLERROR
1080 // look up all the uniform variable names we care about, so we don't
1081 // have to look them up every time we set them
1083 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1084 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1085 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1087 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1088 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1089 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1090 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1095 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1096 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1098 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1102 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1103 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1104 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1114 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1116 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1117 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1118 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1119 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1120 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1121 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1122 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1129 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1130 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1131 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1132 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1134 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1135 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1136 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1137 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1139 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1140 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1141 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1142 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1143 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1144 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1147 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1150 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1151 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1152 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1153 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1154 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1155 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1156 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1157 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1158 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168 // initialize the samplers to refer to the texture units we use
1169 p->tex_Texture_First = -1;
1170 p->tex_Texture_Second = -1;
1171 p->tex_Texture_GammaRamps = -1;
1172 p->tex_Texture_Normal = -1;
1173 p->tex_Texture_Color = -1;
1174 p->tex_Texture_Gloss = -1;
1175 p->tex_Texture_Glow = -1;
1176 p->tex_Texture_SecondaryNormal = -1;
1177 p->tex_Texture_SecondaryColor = -1;
1178 p->tex_Texture_SecondaryGloss = -1;
1179 p->tex_Texture_SecondaryGlow = -1;
1180 p->tex_Texture_Pants = -1;
1181 p->tex_Texture_Shirt = -1;
1182 p->tex_Texture_FogHeightTexture = -1;
1183 p->tex_Texture_FogMask = -1;
1184 p->tex_Texture_Lightmap = -1;
1185 p->tex_Texture_Deluxemap = -1;
1186 p->tex_Texture_Attenuation = -1;
1187 p->tex_Texture_Cube = -1;
1188 p->tex_Texture_Refraction = -1;
1189 p->tex_Texture_Reflection = -1;
1190 p->tex_Texture_ShadowMap2D = -1;
1191 p->tex_Texture_CubeProjection = -1;
1192 p->tex_Texture_ScreenDepth = -1;
1193 p->tex_Texture_ScreenNormalMap = -1;
1194 p->tex_Texture_ScreenDiffuse = -1;
1195 p->tex_Texture_ScreenSpecular = -1;
1196 p->tex_Texture_ReflectMask = -1;
1197 p->tex_Texture_ReflectCube = -1;
1198 p->tex_Texture_BounceGrid = -1;
1200 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1201 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1202 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1203 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1204 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1205 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1206 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1207 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1209 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1211 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1212 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1213 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1215 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1216 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1217 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1218 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1219 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1220 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1221 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1222 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1223 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1224 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1227 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1228 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1229 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1231 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1234 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1238 Mem_Free(vertexstring);
1240 Mem_Free(geometrystring);
1242 Mem_Free(fragmentstring);
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1247 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248 if (r_glsl_permutation != perm)
1250 r_glsl_permutation = perm;
1251 if (!r_glsl_permutation->program)
1253 if (!r_glsl_permutation->compiled)
1254 R_GLSL_CompilePermutation(perm, mode, permutation);
1255 if (!r_glsl_permutation->program)
1257 // remove features until we find a valid permutation
1259 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1261 // reduce i more quickly whenever it would not remove any bits
1262 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263 if (!(permutation & j))
1266 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267 if (!r_glsl_permutation->compiled)
1268 R_GLSL_CompilePermutation(perm, mode, permutation);
1269 if (r_glsl_permutation->program)
1272 if (i >= SHADERPERMUTATION_COUNT)
1274 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276 qglUseProgram(0);CHECKGLERROR
1277 return; // no bit left to clear, entire mode is broken
1282 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1284 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1300 /// hash lookup data
1301 struct r_hlsl_permutation_s *hashnext;
1303 unsigned int permutation;
1305 /// indicates if we have tried compiling this permutation already
1307 /// NULL if compilation failed
1308 IDirect3DVertexShader9 *vertexshader;
1309 IDirect3DPixelShader9 *pixelshader;
1311 r_hlsl_permutation_t;
1313 typedef enum D3DVSREGISTER_e
1315 D3DVSREGISTER_TexMatrix = 0, // float4x4
1316 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320 D3DVSREGISTER_ModelToLight = 20, // float4x4
1321 D3DVSREGISTER_EyePosition = 24,
1322 D3DVSREGISTER_FogPlane = 25,
1323 D3DVSREGISTER_LightDir = 26,
1324 D3DVSREGISTER_LightPosition = 27,
1328 typedef enum D3DPSREGISTER_e
1330 D3DPSREGISTER_Alpha = 0,
1331 D3DPSREGISTER_BloomBlur_Parameters = 1,
1332 D3DPSREGISTER_ClientTime = 2,
1333 D3DPSREGISTER_Color_Ambient = 3,
1334 D3DPSREGISTER_Color_Diffuse = 4,
1335 D3DPSREGISTER_Color_Specular = 5,
1336 D3DPSREGISTER_Color_Glow = 6,
1337 D3DPSREGISTER_Color_Pants = 7,
1338 D3DPSREGISTER_Color_Shirt = 8,
1339 D3DPSREGISTER_DeferredColor_Ambient = 9,
1340 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341 D3DPSREGISTER_DeferredColor_Specular = 11,
1342 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343 D3DPSREGISTER_DeferredMod_Specular = 13,
1344 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345 D3DPSREGISTER_EyePosition = 15, // unused
1346 D3DPSREGISTER_FogColor = 16,
1347 D3DPSREGISTER_FogHeightFade = 17,
1348 D3DPSREGISTER_FogPlane = 18,
1349 D3DPSREGISTER_FogPlaneViewDist = 19,
1350 D3DPSREGISTER_FogRangeRecip = 20,
1351 D3DPSREGISTER_LightColor = 21,
1352 D3DPSREGISTER_LightDir = 22, // unused
1353 D3DPSREGISTER_LightPosition = 23,
1354 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355 D3DPSREGISTER_PixelSize = 25,
1356 D3DPSREGISTER_ReflectColor = 26,
1357 D3DPSREGISTER_ReflectFactor = 27,
1358 D3DPSREGISTER_ReflectOffset = 28,
1359 D3DPSREGISTER_RefractColor = 29,
1360 D3DPSREGISTER_Saturation = 30,
1361 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363 D3DPSREGISTER_ScreenToDepth = 33,
1364 D3DPSREGISTER_ShadowMap_Parameters = 34,
1365 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366 D3DPSREGISTER_SpecularPower = 36,
1367 D3DPSREGISTER_UserVec1 = 37,
1368 D3DPSREGISTER_UserVec2 = 38,
1369 D3DPSREGISTER_UserVec3 = 39,
1370 D3DPSREGISTER_UserVec4 = 40,
1371 D3DPSREGISTER_ViewTintColor = 41,
1372 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373 D3DPSREGISTER_BloomColorSubtract = 43,
1374 D3DPSREGISTER_ViewToLight = 44, // float4x4
1375 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376 D3DPSREGISTER_NormalmapScrollBlend = 52,
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1390 //unsigned int hashdepth = 0;
1391 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392 r_hlsl_permutation_t *p;
1393 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1395 if (p->mode == mode && p->permutation == permutation)
1397 //if (hashdepth > 10)
1398 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1403 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1405 p->permutation = permutation;
1406 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407 r_hlsl_permutationhash[mode][hashindex] = p;
1408 //if (hashdepth > 10)
1409 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1416 if (!filename || !filename[0])
1418 if (!strcmp(filename, "hlsl/default.hlsl"))
1420 if (!hlslshaderstring)
1422 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423 if (hlslshaderstring)
1424 Con_DPrintf("Loading shaders from file %s...\n", filename);
1426 hlslshaderstring = (char *)builtinhlslshaderstring;
1428 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430 return shaderstring;
1432 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1435 if (printfromdisknotice)
1436 Con_DPrintf("from disk %s... ", filename);
1437 return shaderstring;
1439 return shaderstring;
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1448 DWORD *vsbin = NULL;
1449 DWORD *psbin = NULL;
1450 fs_offset_t vsbinsize;
1451 fs_offset_t psbinsize;
1452 // IDirect3DVertexShader9 *vs = NULL;
1453 // IDirect3DPixelShader9 *ps = NULL;
1454 ID3DXBuffer *vslog = NULL;
1455 ID3DXBuffer *vsbuffer = NULL;
1456 ID3DXConstantTable *vsconstanttable = NULL;
1457 ID3DXBuffer *pslog = NULL;
1458 ID3DXBuffer *psbuffer = NULL;
1459 ID3DXConstantTable *psconstanttable = NULL;
1462 char temp[MAX_INPUTLINE];
1463 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464 qboolean debugshader = gl_paranoid.integer != 0;
1465 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1469 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1472 if ((!vsbin && vertstring) || (!psbin && fragstring))
1474 const char* dllnames_d3dx9 [] =
1498 dllhandle_t d3dx9_dll = NULL;
1499 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502 dllfunction_t d3dx9_dllfuncs[] =
1504 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1505 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1506 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1509 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1511 DWORD shaderflags = 0;
1513 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516 if (vertstring && vertstring[0])
1520 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1526 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1529 vsbinsize = vsbuffer->GetBufferSize();
1530 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532 vsbuffer->Release();
1536 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1541 if (fragstring && fragstring[0])
1545 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1551 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1554 psbinsize = psbuffer->GetBufferSize();
1555 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557 psbuffer->Release();
1561 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1566 Sys_UnloadLibrary(&d3dx9_dll);
1569 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1573 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574 if (FAILED(vsresult))
1575 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577 if (FAILED(psresult))
1578 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1580 // free the shader data
1581 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1588 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589 int vertstring_length = 0;
1590 int geomstring_length = 0;
1591 int fragstring_length = 0;
1593 char *vertexstring, *geometrystring, *fragmentstring;
1594 char *vertstring, *geomstring, *fragstring;
1595 char permutationname[256];
1596 char cachename[256];
1597 int vertstrings_count = 0;
1598 int geomstrings_count = 0;
1599 int fragstrings_count = 0;
1600 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607 p->vertexshader = NULL;
1608 p->pixelshader = NULL;
1610 permutationname[0] = 0;
1612 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1616 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617 strlcat(cachename, "hlsl/", sizeof(cachename));
1619 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620 vertstrings_count = 0;
1621 geomstrings_count = 0;
1622 fragstrings_count = 0;
1623 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1627 // the first pretext is which type of shader to compile as
1628 // (later these will all be bound together as a program object)
1629 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1633 // the second pretext is the mode (for example a light source)
1634 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638 strlcat(cachename, modeinfo->name, sizeof(cachename));
1640 // now add all the permutation pretexts
1641 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1643 if (permutation & (1<<i))
1645 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1653 // keep line numbers correct
1654 vertstrings_list[vertstrings_count++] = "\n";
1655 geomstrings_list[geomstrings_count++] = "\n";
1656 fragstrings_list[fragstrings_count++] = "\n";
1661 R_CompileShader_AddStaticParms(mode, permutation);
1662 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663 vertstrings_count += shaderstaticparms_count;
1664 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665 geomstrings_count += shaderstaticparms_count;
1666 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667 fragstrings_count += shaderstaticparms_count;
1669 // replace spaces in the cachename with _ characters
1670 for (i = 0;cachename[i];i++)
1671 if (cachename[i] == ' ')
1674 // now append the shader text itself
1675 vertstrings_list[vertstrings_count++] = vertexstring;
1676 geomstrings_list[geomstrings_count++] = geometrystring;
1677 fragstrings_list[fragstrings_count++] = fragmentstring;
1679 // if any sources were NULL, clear the respective list
1681 vertstrings_count = 0;
1682 if (!geometrystring)
1683 geomstrings_count = 0;
1684 if (!fragmentstring)
1685 fragstrings_count = 0;
1687 vertstring_length = 0;
1688 for (i = 0;i < vertstrings_count;i++)
1689 vertstring_length += strlen(vertstrings_list[i]);
1690 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1694 geomstring_length = 0;
1695 for (i = 0;i < geomstrings_count;i++)
1696 geomstring_length += strlen(geomstrings_list[i]);
1697 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1701 fragstring_length = 0;
1702 for (i = 0;i < fragstrings_count;i++)
1703 fragstring_length += strlen(fragstrings_list[i]);
1704 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1708 // try to load the cached shader, or generate one
1709 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1711 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1714 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1718 Mem_Free(vertstring);
1720 Mem_Free(geomstring);
1722 Mem_Free(fragstring);
1724 Mem_Free(vertexstring);
1726 Mem_Free(geometrystring);
1728 Mem_Free(fragmentstring);
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 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);}
1734 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);}
1735 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);}
1736 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);}
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 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);}
1741 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);}
1742 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);}
1743 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);}
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1747 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748 if (r_hlsl_permutation != perm)
1750 r_hlsl_permutation = perm;
1751 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1753 if (!r_hlsl_permutation->compiled)
1754 R_HLSL_CompilePermutation(perm, mode, permutation);
1755 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757 // remove features until we find a valid permutation
1759 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1761 // reduce i more quickly whenever it would not remove any bits
1762 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763 if (!(permutation & j))
1766 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767 if (!r_hlsl_permutation->compiled)
1768 R_HLSL_CompilePermutation(perm, mode, permutation);
1769 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1772 if (i >= SHADERPERMUTATION_COUNT)
1774 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776 return; // no bit left to clear, entire mode is broken
1780 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1783 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1791 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1797 void R_GLSL_Restart_f(void)
1799 unsigned int i, limit;
1800 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801 Mem_Free(glslshaderstring);
1802 glslshaderstring = NULL;
1803 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804 Mem_Free(hlslshaderstring);
1805 hlslshaderstring = NULL;
1806 switch(vid.renderpath)
1808 case RENDERPATH_D3D9:
1811 r_hlsl_permutation_t *p;
1812 r_hlsl_permutation = NULL;
1813 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814 for (i = 0;i < limit;i++)
1816 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1818 if (p->vertexshader)
1819 IDirect3DVertexShader9_Release(p->vertexshader);
1821 IDirect3DPixelShader9_Release(p->pixelshader);
1822 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1825 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1829 case RENDERPATH_D3D10:
1830 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1832 case RENDERPATH_D3D11:
1833 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835 case RENDERPATH_GL20:
1836 case RENDERPATH_GLES2:
1838 r_glsl_permutation_t *p;
1839 r_glsl_permutation = NULL;
1840 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841 for (i = 0;i < limit;i++)
1843 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1845 GL_Backend_FreeProgram(p->program);
1846 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1849 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1852 case RENDERPATH_GL11:
1853 case RENDERPATH_GL13:
1854 case RENDERPATH_GLES1:
1856 case RENDERPATH_SOFT:
1861 void R_GLSL_DumpShader_f(void)
1866 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1869 FS_Print(file, "/* The engine may define the following macros:\n");
1870 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1871 for (i = 0;i < SHADERMODE_COUNT;i++)
1872 FS_Print(file, glslshadermodeinfo[i].pretext);
1873 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1874 FS_Print(file, shaderpermutationinfo[i].pretext);
1875 FS_Print(file, "*/\n");
1876 FS_Print(file, builtinshaderstring);
1878 Con_Printf("glsl/default.glsl written\n");
1881 Con_Printf("failed to write to glsl/default.glsl\n");
1883 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1886 FS_Print(file, "/* The engine may define the following macros:\n");
1887 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1888 for (i = 0;i < SHADERMODE_COUNT;i++)
1889 FS_Print(file, hlslshadermodeinfo[i].pretext);
1890 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1891 FS_Print(file, shaderpermutationinfo[i].pretext);
1892 FS_Print(file, "*/\n");
1893 FS_Print(file, builtinhlslshaderstring);
1895 Con_Printf("hlsl/default.hlsl written\n");
1898 Con_Printf("failed to write to hlsl/default.hlsl\n");
1901 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1904 texturemode = GL_MODULATE;
1905 switch (vid.renderpath)
1907 case RENDERPATH_D3D9:
1909 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))));
1910 R_Mesh_TexBind(GL20TU_FIRST , first );
1911 R_Mesh_TexBind(GL20TU_SECOND, second);
1914 case RENDERPATH_D3D10:
1915 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1917 case RENDERPATH_D3D11:
1918 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920 case RENDERPATH_GL20:
1921 case RENDERPATH_GLES2:
1922 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))));
1923 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1924 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1926 case RENDERPATH_GL13:
1927 case RENDERPATH_GLES1:
1928 R_Mesh_TexBind(0, first );
1929 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1930 R_Mesh_TexBind(1, second);
1932 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1934 case RENDERPATH_GL11:
1935 R_Mesh_TexBind(0, first );
1937 case RENDERPATH_SOFT:
1938 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))));
1939 R_Mesh_TexBind(GL20TU_FIRST , first );
1940 R_Mesh_TexBind(GL20TU_SECOND, second);
1945 void R_SetupShader_DepthOrShadow(void)
1947 switch (vid.renderpath)
1949 case RENDERPATH_D3D9:
1951 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1954 case RENDERPATH_D3D10:
1955 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957 case RENDERPATH_D3D11:
1958 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960 case RENDERPATH_GL20:
1961 case RENDERPATH_GLES2:
1962 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1964 case RENDERPATH_GL13:
1965 case RENDERPATH_GLES1:
1966 R_Mesh_TexBind(0, 0);
1967 R_Mesh_TexBind(1, 0);
1969 case RENDERPATH_GL11:
1970 R_Mesh_TexBind(0, 0);
1972 case RENDERPATH_SOFT:
1973 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1978 void R_SetupShader_ShowDepth(void)
1980 switch (vid.renderpath)
1982 case RENDERPATH_D3D9:
1984 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1987 case RENDERPATH_D3D10:
1988 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990 case RENDERPATH_D3D11:
1991 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1993 case RENDERPATH_GL20:
1994 case RENDERPATH_GLES2:
1995 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1997 case RENDERPATH_GL13:
1998 case RENDERPATH_GLES1:
2000 case RENDERPATH_GL11:
2002 case RENDERPATH_SOFT:
2003 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2008 extern qboolean r_shadow_usingdeferredprepass;
2009 extern cvar_t r_shadow_deferred_8bitrange;
2010 extern rtexture_t *r_shadow_attenuationgradienttexture;
2011 extern rtexture_t *r_shadow_attenuation2dtexture;
2012 extern rtexture_t *r_shadow_attenuation3dtexture;
2013 extern qboolean r_shadow_usingshadowmap2d;
2014 extern qboolean r_shadow_usingshadowmaportho;
2015 extern float r_shadow_shadowmap_texturescale[2];
2016 extern float r_shadow_shadowmap_parameters[4];
2017 extern qboolean r_shadow_shadowmapvsdct;
2018 extern qboolean r_shadow_shadowmapsampler;
2019 extern int r_shadow_shadowmappcf;
2020 extern rtexture_t *r_shadow_shadowmap2dtexture;
2021 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2022 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2023 extern matrix4x4_t r_shadow_shadowmapmatrix;
2024 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2025 extern int r_shadow_prepass_width;
2026 extern int r_shadow_prepass_height;
2027 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2028 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2029 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2030 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2031 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2033 #define BLENDFUNC_ALLOWS_COLORMOD 1
2034 #define BLENDFUNC_ALLOWS_FOG 2
2035 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2036 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2037 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2038 static int R_BlendFuncFlags(int src, int dst)
2042 // a blendfunc allows colormod if:
2043 // a) it can never keep the destination pixel invariant, or
2044 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2045 // this is to prevent unintended side effects from colormod
2047 // a blendfunc allows fog if:
2048 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2049 // this is to prevent unintended side effects from fog
2051 // these checks are the output of fogeval.pl
2053 r |= BLENDFUNC_ALLOWS_COLORMOD;
2054 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2055 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2056 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2058 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2063 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2064 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2065 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2066 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2067 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2069 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2070 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2072 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2073 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2074 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2079 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)
2081 // select a permutation of the lighting shader appropriate to this
2082 // combination of texture, entity, light source, and fogging, only use the
2083 // minimum features necessary to avoid wasting rendering time in the
2084 // fragment shader on features that are not being used
2085 unsigned int permutation = 0;
2086 unsigned int mode = 0;
2088 static float dummy_colormod[3] = {1, 1, 1};
2089 float *colormod = rsurface.colormod;
2091 matrix4x4_t tempmatrix;
2092 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2093 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2094 permutation |= SHADERPERMUTATION_ALPHAKILL;
2095 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2096 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2097 if (rsurfacepass == RSURFPASS_BACKGROUND)
2099 // distorted background
2100 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2102 mode = SHADERMODE_WATER;
2103 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2105 // this is the right thing to do for wateralpha
2106 GL_BlendFunc(GL_ONE, GL_ZERO);
2107 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2111 // this is the right thing to do for entity alpha
2112 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2113 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2116 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2118 mode = SHADERMODE_REFRACTION;
2119 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2120 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2124 mode = SHADERMODE_GENERIC;
2125 permutation |= SHADERPERMUTATION_DIFFUSE;
2126 GL_BlendFunc(GL_ONE, GL_ZERO);
2127 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2130 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2132 if (r_glsl_offsetmapping.integer)
2134 switch(rsurface.texture->offsetmapping)
2136 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2137 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2138 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2139 case OFFSETMAPPING_OFF: break;
2142 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2143 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2144 // normalmap (deferred prepass), may use alpha test on diffuse
2145 mode = SHADERMODE_DEFERREDGEOMETRY;
2146 GL_BlendFunc(GL_ONE, GL_ZERO);
2147 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2149 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2151 if (r_glsl_offsetmapping.integer)
2153 switch(rsurface.texture->offsetmapping)
2155 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2156 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2157 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2158 case OFFSETMAPPING_OFF: break;
2161 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2162 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2164 mode = SHADERMODE_LIGHTSOURCE;
2165 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2166 permutation |= SHADERPERMUTATION_CUBEFILTER;
2167 if (diffusescale > 0)
2168 permutation |= SHADERPERMUTATION_DIFFUSE;
2169 if (specularscale > 0)
2170 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2171 if (r_refdef.fogenabled)
2172 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2173 if (rsurface.texture->colormapping)
2174 permutation |= SHADERPERMUTATION_COLORMAPPING;
2175 if (r_shadow_usingshadowmap2d)
2177 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2178 if(r_shadow_shadowmapvsdct)
2179 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2181 if (r_shadow_shadowmapsampler)
2182 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2183 if (r_shadow_shadowmappcf > 1)
2184 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2185 else if (r_shadow_shadowmappcf)
2186 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2188 if (rsurface.texture->reflectmasktexture)
2189 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2190 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2191 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2193 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2195 if (r_glsl_offsetmapping.integer)
2197 switch(rsurface.texture->offsetmapping)
2199 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2200 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202 case OFFSETMAPPING_OFF: break;
2205 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2206 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2207 // unshaded geometry (fullbright or ambient model lighting)
2208 mode = SHADERMODE_FLATCOLOR;
2209 ambientscale = diffusescale = specularscale = 0;
2210 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2211 permutation |= SHADERPERMUTATION_GLOW;
2212 if (r_refdef.fogenabled)
2213 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2214 if (rsurface.texture->colormapping)
2215 permutation |= SHADERPERMUTATION_COLORMAPPING;
2216 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2218 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2219 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2221 if (r_shadow_shadowmapsampler)
2222 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2223 if (r_shadow_shadowmappcf > 1)
2224 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2225 else if (r_shadow_shadowmappcf)
2226 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2228 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2229 permutation |= SHADERPERMUTATION_REFLECTION;
2230 if (rsurface.texture->reflectmasktexture)
2231 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2232 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2233 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2235 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2237 if (r_glsl_offsetmapping.integer)
2239 switch(rsurface.texture->offsetmapping)
2241 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2242 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2243 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2244 case OFFSETMAPPING_OFF: break;
2247 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2248 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2249 // directional model lighting
2250 mode = SHADERMODE_LIGHTDIRECTION;
2251 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2252 permutation |= SHADERPERMUTATION_GLOW;
2253 permutation |= SHADERPERMUTATION_DIFFUSE;
2254 if (specularscale > 0)
2255 permutation |= SHADERPERMUTATION_SPECULAR;
2256 if (r_refdef.fogenabled)
2257 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2258 if (rsurface.texture->colormapping)
2259 permutation |= SHADERPERMUTATION_COLORMAPPING;
2260 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2262 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2263 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2265 if (r_shadow_shadowmapsampler)
2266 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2267 if (r_shadow_shadowmappcf > 1)
2268 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2269 else if (r_shadow_shadowmappcf)
2270 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2272 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2273 permutation |= SHADERPERMUTATION_REFLECTION;
2274 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2275 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2276 if (rsurface.texture->reflectmasktexture)
2277 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2278 if (r_shadow_bouncegridtexture)
2280 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2281 if (r_shadow_bouncegriddirectional)
2282 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2284 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2285 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2287 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2289 if (r_glsl_offsetmapping.integer)
2291 switch(rsurface.texture->offsetmapping)
2293 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2294 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2295 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296 case OFFSETMAPPING_OFF: break;
2299 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2300 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2301 // ambient model lighting
2302 mode = SHADERMODE_LIGHTDIRECTION;
2303 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2304 permutation |= SHADERPERMUTATION_GLOW;
2305 if (r_refdef.fogenabled)
2306 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2307 if (rsurface.texture->colormapping)
2308 permutation |= SHADERPERMUTATION_COLORMAPPING;
2309 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2311 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2312 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2314 if (r_shadow_shadowmapsampler)
2315 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2316 if (r_shadow_shadowmappcf > 1)
2317 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2318 else if (r_shadow_shadowmappcf)
2319 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2321 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2322 permutation |= SHADERPERMUTATION_REFLECTION;
2323 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2324 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2325 if (rsurface.texture->reflectmasktexture)
2326 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2327 if (r_shadow_bouncegridtexture)
2329 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2330 if (r_shadow_bouncegriddirectional)
2331 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2333 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2334 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2338 if (r_glsl_offsetmapping.integer)
2340 switch(rsurface.texture->offsetmapping)
2342 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2343 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2344 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2345 case OFFSETMAPPING_OFF: break;
2348 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2349 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2351 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2352 permutation |= SHADERPERMUTATION_GLOW;
2353 if (r_refdef.fogenabled)
2354 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2355 if (rsurface.texture->colormapping)
2356 permutation |= SHADERPERMUTATION_COLORMAPPING;
2357 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2359 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2360 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2362 if (r_shadow_shadowmapsampler)
2363 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2364 if (r_shadow_shadowmappcf > 1)
2365 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2366 else if (r_shadow_shadowmappcf)
2367 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2369 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2370 permutation |= SHADERPERMUTATION_REFLECTION;
2371 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2372 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2373 if (rsurface.texture->reflectmasktexture)
2374 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2375 if (FAKELIGHT_ENABLED)
2377 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2378 mode = SHADERMODE_FAKELIGHT;
2379 permutation |= SHADERPERMUTATION_DIFFUSE;
2380 if (specularscale > 0)
2381 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2383 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2385 // deluxemapping (light direction texture)
2386 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2387 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2389 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2390 permutation |= SHADERPERMUTATION_DIFFUSE;
2391 if (specularscale > 0)
2392 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2394 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2396 // fake deluxemapping (uniform light direction in tangentspace)
2397 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2398 permutation |= SHADERPERMUTATION_DIFFUSE;
2399 if (specularscale > 0)
2400 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2402 else if (rsurface.uselightmaptexture)
2404 // ordinary lightmapping (q1bsp, q3bsp)
2405 mode = SHADERMODE_LIGHTMAP;
2409 // ordinary vertex coloring (q3bsp)
2410 mode = SHADERMODE_VERTEXCOLOR;
2412 if (r_shadow_bouncegridtexture)
2414 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2415 if (r_shadow_bouncegriddirectional)
2416 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2418 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2419 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2422 colormod = dummy_colormod;
2423 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2424 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2425 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2426 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2427 switch(vid.renderpath)
2429 case RENDERPATH_D3D9:
2431 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);
2432 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2433 R_SetupShader_SetPermutationHLSL(mode, permutation);
2434 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2435 if (mode == SHADERMODE_LIGHTSOURCE)
2437 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2438 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2442 if (mode == SHADERMODE_LIGHTDIRECTION)
2444 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2447 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2448 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2449 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2450 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2451 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2453 if (mode == SHADERMODE_LIGHTSOURCE)
2455 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2456 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2457 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2458 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2459 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2461 // additive passes are only darkened by fog, not tinted
2462 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2463 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2467 if (mode == SHADERMODE_FLATCOLOR)
2469 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2471 else if (mode == SHADERMODE_LIGHTDIRECTION)
2473 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]);
2474 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2475 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);
2476 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);
2477 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2478 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2479 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2483 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2484 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2485 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);
2486 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);
2487 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2489 // additive passes are only darkened by fog, not tinted
2490 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2491 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2493 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2494 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);
2495 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2496 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2497 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2498 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2499 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2500 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2501 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2502 if (mode == SHADERMODE_WATER)
2503 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2505 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2506 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2507 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2508 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));
2509 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2510 if (rsurface.texture->pantstexture)
2511 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2513 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2514 if (rsurface.texture->shirttexture)
2515 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2517 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2518 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2519 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2520 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2521 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2522 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2523 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2524 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2525 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2526 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2528 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2529 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2531 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2532 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2533 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2534 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2535 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2536 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2537 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2538 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2539 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2540 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2541 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2542 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2543 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2544 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2545 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2546 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2547 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2548 if (rsurfacepass == RSURFPASS_BACKGROUND)
2550 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2551 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2552 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2556 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2558 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2559 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2560 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2561 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2562 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2564 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2565 if (rsurface.rtlight)
2567 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2568 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2573 case RENDERPATH_D3D10:
2574 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2576 case RENDERPATH_D3D11:
2577 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2579 case RENDERPATH_GL20:
2580 case RENDERPATH_GLES2:
2581 if (!vid.useinterleavedarrays)
2583 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);
2584 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2585 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2586 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2587 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2588 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2589 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2590 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2594 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);
2595 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2597 R_SetupShader_SetPermutationGLSL(mode, permutation);
2598 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2599 if (mode == SHADERMODE_LIGHTSOURCE)
2601 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2602 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2603 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2604 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2605 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2606 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);
2608 // additive passes are only darkened by fog, not tinted
2609 if (r_glsl_permutation->loc_FogColor >= 0)
2610 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2611 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2615 if (mode == SHADERMODE_FLATCOLOR)
2617 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2619 else if (mode == SHADERMODE_LIGHTDIRECTION)
2621 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]);
2622 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]);
2623 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);
2624 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);
2625 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);
2626 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]);
2627 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]);
2631 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]);
2632 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]);
2633 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);
2634 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);
2635 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);
2637 // additive passes are only darkened by fog, not tinted
2638 if (r_glsl_permutation->loc_FogColor >= 0)
2640 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2641 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2643 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2645 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);
2646 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]);
2647 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]);
2648 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]);
2649 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]);
2650 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2651 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2652 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2653 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]);
2655 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2656 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2657 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2658 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]);
2659 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]);
2661 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2662 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));
2663 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2664 if (r_glsl_permutation->loc_Color_Pants >= 0)
2666 if (rsurface.texture->pantstexture)
2667 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2669 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2671 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2673 if (rsurface.texture->shirttexture)
2674 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2676 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2678 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]);
2679 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2680 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2681 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2682 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2683 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2684 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2685 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2688 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]);
2689 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2690 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);}
2691 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2693 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2694 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2695 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2696 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2697 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2698 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2699 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2700 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2701 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2702 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2703 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2704 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2705 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2706 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2707 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);
2708 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2709 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2710 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2711 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2712 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2713 if (rsurfacepass == RSURFPASS_BACKGROUND)
2715 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);
2716 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);
2717 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);
2721 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);
2723 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2724 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2725 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2726 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2727 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2729 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2730 if (rsurface.rtlight)
2732 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2733 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2736 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2739 case RENDERPATH_GL11:
2740 case RENDERPATH_GL13:
2741 case RENDERPATH_GLES1:
2743 case RENDERPATH_SOFT:
2744 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);
2745 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2746 R_SetupShader_SetPermutationSoft(mode, permutation);
2747 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2748 if (mode == SHADERMODE_LIGHTSOURCE)
2750 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2751 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2752 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2753 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2757 // additive passes are only darkened by fog, not tinted
2758 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2759 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2763 if (mode == SHADERMODE_FLATCOLOR)
2765 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2767 else if (mode == SHADERMODE_LIGHTDIRECTION)
2769 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]);
2770 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2771 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);
2772 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);
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2774 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]);
2775 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2779 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2781 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);
2782 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);
2783 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2785 // additive passes are only darkened by fog, not tinted
2786 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2789 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2790 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);
2791 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2792 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2793 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]);
2794 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]);
2795 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2796 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2797 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2798 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2800 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2801 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2802 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2803 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2804 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]);
2806 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2807 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));
2808 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2809 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2811 if (rsurface.texture->pantstexture)
2812 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2814 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2816 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2818 if (rsurface.texture->shirttexture)
2819 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2821 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2823 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2824 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2825 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2826 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2827 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2828 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2829 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2830 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2831 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2833 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2834 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2836 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2837 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2838 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2839 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2840 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2841 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2842 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2843 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2844 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2845 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2846 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2847 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2848 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2849 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2850 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2851 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2852 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2853 if (rsurfacepass == RSURFPASS_BACKGROUND)
2855 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2856 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2857 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2861 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2863 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2864 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2865 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2866 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2867 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2869 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2870 if (rsurface.rtlight)
2872 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2873 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2880 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2882 // select a permutation of the lighting shader appropriate to this
2883 // combination of texture, entity, light source, and fogging, only use the
2884 // minimum features necessary to avoid wasting rendering time in the
2885 // fragment shader on features that are not being used
2886 unsigned int permutation = 0;
2887 unsigned int mode = 0;
2888 const float *lightcolorbase = rtlight->currentcolor;
2889 float ambientscale = rtlight->ambientscale;
2890 float diffusescale = rtlight->diffusescale;
2891 float specularscale = rtlight->specularscale;
2892 // this is the location of the light in view space
2893 vec3_t viewlightorigin;
2894 // this transforms from view space (camera) to light space (cubemap)
2895 matrix4x4_t viewtolight;
2896 matrix4x4_t lighttoview;
2897 float viewtolight16f[16];
2898 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2900 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2901 if (rtlight->currentcubemap != r_texture_whitecube)
2902 permutation |= SHADERPERMUTATION_CUBEFILTER;
2903 if (diffusescale > 0)
2904 permutation |= SHADERPERMUTATION_DIFFUSE;
2905 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2906 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2907 if (r_shadow_usingshadowmap2d)
2909 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2910 if (r_shadow_shadowmapvsdct)
2911 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2913 if (r_shadow_shadowmapsampler)
2914 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2915 if (r_shadow_shadowmappcf > 1)
2916 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2917 else if (r_shadow_shadowmappcf)
2918 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2920 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2921 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2922 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2923 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2924 switch(vid.renderpath)
2926 case RENDERPATH_D3D9:
2928 R_SetupShader_SetPermutationHLSL(mode, permutation);
2929 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2930 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2931 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2932 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2933 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2934 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2935 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2936 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2937 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2938 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2940 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2941 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2942 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2943 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2944 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2945 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2948 case RENDERPATH_D3D10:
2949 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2951 case RENDERPATH_D3D11:
2952 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2954 case RENDERPATH_GL20:
2955 case RENDERPATH_GLES2:
2956 R_SetupShader_SetPermutationGLSL(mode, permutation);
2957 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2958 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2959 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);
2960 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);
2961 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);
2962 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]);
2963 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]);
2964 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));
2965 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]);
2966 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2968 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2969 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2970 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2971 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2972 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2973 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2975 case RENDERPATH_GL11:
2976 case RENDERPATH_GL13:
2977 case RENDERPATH_GLES1:
2979 case RENDERPATH_SOFT:
2980 R_SetupShader_SetPermutationGLSL(mode, permutation);
2981 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2982 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2983 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2984 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2985 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2986 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2987 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]);
2988 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));
2989 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2990 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2992 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2993 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2994 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2995 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2996 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2997 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3002 #define SKINFRAME_HASH 1024
3006 int loadsequence; // incremented each level change
3007 memexpandablearray_t array;
3008 skinframe_t *hash[SKINFRAME_HASH];
3011 r_skinframe_t r_skinframe;
3013 void R_SkinFrame_PrepareForPurge(void)
3015 r_skinframe.loadsequence++;
3016 // wrap it without hitting zero
3017 if (r_skinframe.loadsequence >= 200)
3018 r_skinframe.loadsequence = 1;
3021 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3025 // mark the skinframe as used for the purging code
3026 skinframe->loadsequence = r_skinframe.loadsequence;
3029 void R_SkinFrame_Purge(void)
3033 for (i = 0;i < SKINFRAME_HASH;i++)
3035 for (s = r_skinframe.hash[i];s;s = s->next)
3037 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3039 if (s->merged == s->base)
3041 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3042 R_PurgeTexture(s->stain );s->stain = NULL;
3043 R_PurgeTexture(s->merged);s->merged = NULL;
3044 R_PurgeTexture(s->base );s->base = NULL;
3045 R_PurgeTexture(s->pants );s->pants = NULL;
3046 R_PurgeTexture(s->shirt );s->shirt = NULL;
3047 R_PurgeTexture(s->nmap );s->nmap = NULL;
3048 R_PurgeTexture(s->gloss );s->gloss = NULL;
3049 R_PurgeTexture(s->glow );s->glow = NULL;
3050 R_PurgeTexture(s->fog );s->fog = NULL;
3051 R_PurgeTexture(s->reflect);s->reflect = NULL;
3052 s->loadsequence = 0;
3058 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3060 char basename[MAX_QPATH];
3062 Image_StripImageExtension(name, basename, sizeof(basename));
3064 if( last == NULL ) {
3066 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3067 item = r_skinframe.hash[hashindex];
3072 // linearly search through the hash bucket
3073 for( ; item ; item = item->next ) {
3074 if( !strcmp( item->basename, basename ) ) {
3081 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3085 char basename[MAX_QPATH];
3087 Image_StripImageExtension(name, basename, sizeof(basename));
3089 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3090 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3091 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3095 rtexture_t *dyntexture;
3096 // check whether its a dynamic texture
3097 dyntexture = CL_GetDynTexture( basename );
3098 if (!add && !dyntexture)
3100 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3101 memset(item, 0, sizeof(*item));
3102 strlcpy(item->basename, basename, sizeof(item->basename));
3103 item->base = dyntexture; // either NULL or dyntexture handle
3104 item->textureflags = textureflags;
3105 item->comparewidth = comparewidth;
3106 item->compareheight = compareheight;
3107 item->comparecrc = comparecrc;
3108 item->next = r_skinframe.hash[hashindex];
3109 r_skinframe.hash[hashindex] = item;
3111 else if( item->base == NULL )
3113 rtexture_t *dyntexture;
3114 // check whether its a dynamic texture
3115 // 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]
3116 dyntexture = CL_GetDynTexture( basename );
3117 item->base = dyntexture; // either NULL or dyntexture handle
3120 R_SkinFrame_MarkUsed(item);
3124 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3126 unsigned long long avgcolor[5], wsum; \
3134 for(pix = 0; pix < cnt; ++pix) \
3137 for(comp = 0; comp < 3; ++comp) \
3139 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3142 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144 for(comp = 0; comp < 3; ++comp) \
3145 avgcolor[comp] += getpixel * w; \
3148 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3149 avgcolor[4] += getpixel; \
3151 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3153 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3154 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3155 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3156 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3159 extern cvar_t gl_picmip;
3160 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3163 unsigned char *pixels;
3164 unsigned char *bumppixels;
3165 unsigned char *basepixels = NULL;
3166 int basepixels_width = 0;
3167 int basepixels_height = 0;
3168 skinframe_t *skinframe;
3169 rtexture_t *ddsbase = NULL;
3170 qboolean ddshasalpha = false;
3171 float ddsavgcolor[4];
3172 char basename[MAX_QPATH];
3173 int miplevel = R_PicmipForFlags(textureflags);
3174 int savemiplevel = miplevel;
3177 if (cls.state == ca_dedicated)
3180 // return an existing skinframe if already loaded
3181 // if loading of the first image fails, don't make a new skinframe as it
3182 // would cause all future lookups of this to be missing
3183 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3184 if (skinframe && skinframe->base)
3187 Image_StripImageExtension(name, basename, sizeof(basename));
3189 // check for DDS texture file first
3190 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3192 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3193 if (basepixels == NULL)
3197 // FIXME handle miplevel
3199 if (developer_loading.integer)
3200 Con_Printf("loading skin \"%s\"\n", name);
3202 // we've got some pixels to store, so really allocate this new texture now
3204 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3205 skinframe->stain = NULL;
3206 skinframe->merged = NULL;
3207 skinframe->base = NULL;
3208 skinframe->pants = NULL;
3209 skinframe->shirt = NULL;
3210 skinframe->nmap = NULL;
3211 skinframe->gloss = NULL;
3212 skinframe->glow = NULL;
3213 skinframe->fog = NULL;
3214 skinframe->reflect = NULL;
3215 skinframe->hasalpha = false;
3219 skinframe->base = ddsbase;
3220 skinframe->hasalpha = ddshasalpha;
3221 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3222 if (r_loadfog && skinframe->hasalpha)
3223 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3224 //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]);
3228 basepixels_width = image_width;
3229 basepixels_height = image_height;
3230 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);
3231 if (textureflags & TEXF_ALPHA)
3233 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3235 if (basepixels[j] < 255)
3237 skinframe->hasalpha = true;
3241 if (r_loadfog && skinframe->hasalpha)
3243 // has transparent pixels
3244 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3245 for (j = 0;j < image_width * image_height * 4;j += 4)
3250 pixels[j+3] = basepixels[j+3];
3252 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);
3256 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3257 //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]);
3258 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3259 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3260 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3261 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3266 mymiplevel = savemiplevel;
3267 if (r_loadnormalmap)
3268 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);
3269 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3271 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3277 // _norm is the name used by tenebrae and has been adopted as standard
3278 if (r_loadnormalmap && skinframe->nmap == NULL)
3280 mymiplevel = savemiplevel;
3281 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3283 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);
3287 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3289 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3290 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3291 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3293 Mem_Free(bumppixels);
3295 else if (r_shadow_bumpscale_basetexture.value > 0)
3297 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3298 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3299 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);
3302 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3303 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3306 // _luma is supported only for tenebrae compatibility
3307 // _glow is the preferred name
3308 mymiplevel = savemiplevel;
3309 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))))
3311 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);
3312 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3313 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3314 Mem_Free(pixels);pixels = NULL;
3317 mymiplevel = savemiplevel;
3318 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3320 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);
3321 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3322 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3327 mymiplevel = savemiplevel;
3328 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3330 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);
3331 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3332 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3337 mymiplevel = savemiplevel;
3338 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3340 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);
3341 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3342 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3347 mymiplevel = savemiplevel;
3348 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3350 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);
3351 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3352 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3358 Mem_Free(basepixels);
3363 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3364 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3367 unsigned char *temp1, *temp2;
3368 skinframe_t *skinframe;
3370 if (cls.state == ca_dedicated)
3373 // if already loaded just return it, otherwise make a new skinframe
3374 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3375 if (skinframe && skinframe->base)
3378 skinframe->stain = NULL;
3379 skinframe->merged = NULL;
3380 skinframe->base = NULL;
3381 skinframe->pants = NULL;
3382 skinframe->shirt = NULL;
3383 skinframe->nmap = NULL;
3384 skinframe->gloss = NULL;
3385 skinframe->glow = NULL;
3386 skinframe->fog = NULL;
3387 skinframe->reflect = NULL;
3388 skinframe->hasalpha = false;
3390 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3394 if (developer_loading.integer)
3395 Con_Printf("loading 32bit skin \"%s\"\n", name);
3397 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3399 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3400 temp2 = temp1 + width * height * 4;
3401 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3402 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);
3405 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3406 if (textureflags & TEXF_ALPHA)
3408 for (i = 3;i < width * height * 4;i += 4)
3410 if (skindata[i] < 255)
3412 skinframe->hasalpha = true;
3416 if (r_loadfog && skinframe->hasalpha)
3418 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3419 memcpy(fogpixels, skindata, width * height * 4);
3420 for (i = 0;i < width * height * 4;i += 4)
3421 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3422 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3423 Mem_Free(fogpixels);
3427 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3428 //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]);
3433 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3437 skinframe_t *skinframe;
3439 if (cls.state == ca_dedicated)
3442 // if already loaded just return it, otherwise make a new skinframe
3443 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3444 if (skinframe && skinframe->base)
3447 skinframe->stain = NULL;
3448 skinframe->merged = NULL;
3449 skinframe->base = NULL;
3450 skinframe->pants = NULL;
3451 skinframe->shirt = NULL;
3452 skinframe->nmap = NULL;
3453 skinframe->gloss = NULL;
3454 skinframe->glow = NULL;
3455 skinframe->fog = NULL;
3456 skinframe->reflect = NULL;
3457 skinframe->hasalpha = false;
3459 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3463 if (developer_loading.integer)
3464 Con_Printf("loading quake skin \"%s\"\n", name);
3466 // 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)
3467 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3468 memcpy(skinframe->qpixels, skindata, width*height);
3469 skinframe->qwidth = width;
3470 skinframe->qheight = height;
3473 for (i = 0;i < width * height;i++)
3474 featuresmask |= palette_featureflags[skindata[i]];
3476 skinframe->hasalpha = false;
3477 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3478 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3479 skinframe->qgeneratemerged = true;
3480 skinframe->qgeneratebase = skinframe->qhascolormapping;
3481 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3483 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3484 //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]);
3489 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3493 unsigned char *skindata;
3495 if (!skinframe->qpixels)
3498 if (!skinframe->qhascolormapping)
3499 colormapped = false;
3503 if (!skinframe->qgeneratebase)
3508 if (!skinframe->qgeneratemerged)
3512 width = skinframe->qwidth;
3513 height = skinframe->qheight;
3514 skindata = skinframe->qpixels;
3516 if (skinframe->qgeneratenmap)
3518 unsigned char *temp1, *temp2;
3519 skinframe->qgeneratenmap = false;
3520 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3521 temp2 = temp1 + width * height * 4;
3522 // use either a custom palette or the quake palette
3523 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3524 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3525 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);
3529 if (skinframe->qgenerateglow)
3531 skinframe->qgenerateglow = false;
3532 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
3537 skinframe->qgeneratebase = false;
3538 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);
3539 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);
3540 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);
3544 skinframe->qgeneratemerged = false;
3545 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);
3548 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3550 Mem_Free(skinframe->qpixels);
3551 skinframe->qpixels = NULL;
3555 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)
3558 skinframe_t *skinframe;
3560 if (cls.state == ca_dedicated)
3563 // if already loaded just return it, otherwise make a new skinframe
3564 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3565 if (skinframe && skinframe->base)
3568 skinframe->stain = NULL;
3569 skinframe->merged = NULL;
3570 skinframe->base = NULL;
3571 skinframe->pants = NULL;
3572 skinframe->shirt = NULL;
3573 skinframe->nmap = NULL;
3574 skinframe->gloss = NULL;
3575 skinframe->glow = NULL;
3576 skinframe->fog = NULL;
3577 skinframe->reflect = NULL;
3578 skinframe->hasalpha = false;
3580 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3584 if (developer_loading.integer)
3585 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3587 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3588 if (textureflags & TEXF_ALPHA)
3590 for (i = 0;i < width * height;i++)
3592 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3594 skinframe->hasalpha = true;
3598 if (r_loadfog && skinframe->hasalpha)
3599 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3602 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3603 //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]);
3608 skinframe_t *R_SkinFrame_LoadMissing(void)
3610 skinframe_t *skinframe;
3612 if (cls.state == ca_dedicated)
3615 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3616 skinframe->stain = NULL;
3617 skinframe->merged = NULL;
3618 skinframe->base = NULL;
3619 skinframe->pants = NULL;
3620 skinframe->shirt = NULL;
3621 skinframe->nmap = NULL;
3622 skinframe->gloss = NULL;
3623 skinframe->glow = NULL;
3624 skinframe->fog = NULL;
3625 skinframe->reflect = NULL;
3626 skinframe->hasalpha = false;
3628 skinframe->avgcolor[0] = rand() / RAND_MAX;
3629 skinframe->avgcolor[1] = rand() / RAND_MAX;
3630 skinframe->avgcolor[2] = rand() / RAND_MAX;
3631 skinframe->avgcolor[3] = 1;
3636 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3637 typedef struct suffixinfo_s
3640 qboolean flipx, flipy, flipdiagonal;
3643 static suffixinfo_t suffix[3][6] =
3646 {"px", false, false, false},
3647 {"nx", false, false, false},
3648 {"py", false, false, false},
3649 {"ny", false, false, false},
3650 {"pz", false, false, false},
3651 {"nz", false, false, false}
3654 {"posx", false, false, false},
3655 {"negx", false, false, false},
3656 {"posy", false, false, false},
3657 {"negy", false, false, false},
3658 {"posz", false, false, false},
3659 {"negz", false, false, false}
3662 {"rt", true, false, true},
3663 {"lf", false, true, true},
3664 {"ft", true, true, false},
3665 {"bk", false, false, false},
3666 {"up", true, false, true},
3667 {"dn", true, false, true}
3671 static int componentorder[4] = {0, 1, 2, 3};
3673 rtexture_t *R_LoadCubemap(const char *basename)
3675 int i, j, cubemapsize;
3676 unsigned char *cubemappixels, *image_buffer;
3677 rtexture_t *cubemaptexture;
3679 // must start 0 so the first loadimagepixels has no requested width/height
3681 cubemappixels = NULL;
3682 cubemaptexture = NULL;
3683 // keep trying different suffix groups (posx, px, rt) until one loads
3684 for (j = 0;j < 3 && !cubemappixels;j++)
3686 // load the 6 images in the suffix group
3687 for (i = 0;i < 6;i++)
3689 // generate an image name based on the base and and suffix
3690 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3692 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3694 // an image loaded, make sure width and height are equal
3695 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3697 // if this is the first image to load successfully, allocate the cubemap memory
3698 if (!cubemappixels && image_width >= 1)
3700 cubemapsize = image_width;
3701 // note this clears to black, so unavailable sides are black
3702 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3704 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3706 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);
3709 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3711 Mem_Free(image_buffer);
3715 // if a cubemap loaded, upload it
3718 if (developer_loading.integer)
3719 Con_Printf("loading cubemap \"%s\"\n", basename);
3721 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);
3722 Mem_Free(cubemappixels);
3726 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3727 if (developer_loading.integer)
3729 Con_Printf("(tried tried images ");
3730 for (j = 0;j < 3;j++)
3731 for (i = 0;i < 6;i++)
3732 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3733 Con_Print(" and was unable to find any of them).\n");
3736 return cubemaptexture;
3739 rtexture_t *R_GetCubemap(const char *basename)
3742 for (i = 0;i < r_texture_numcubemaps;i++)
3743 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3744 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3745 if (i >= MAX_CUBEMAPS)
3746 return r_texture_whitecube;
3747 r_texture_numcubemaps++;
3748 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3749 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3750 return r_texture_cubemaps[i].texture;
3753 void R_FreeCubemaps(void)
3756 for (i = 0;i < r_texture_numcubemaps;i++)
3758 if (developer_loading.integer)
3759 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3760 if (r_texture_cubemaps[i].texture)
3761 R_FreeTexture(r_texture_cubemaps[i].texture);
3763 r_texture_numcubemaps = 0;
3766 void R_Main_FreeViewCache(void)
3768 if (r_refdef.viewcache.entityvisible)
3769 Mem_Free(r_refdef.viewcache.entityvisible);
3770 if (r_refdef.viewcache.world_pvsbits)
3771 Mem_Free(r_refdef.viewcache.world_pvsbits);
3772 if (r_refdef.viewcache.world_leafvisible)
3773 Mem_Free(r_refdef.viewcache.world_leafvisible);
3774 if (r_refdef.viewcache.world_surfacevisible)
3775 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3776 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3779 void R_Main_ResizeViewCache(void)
3781 int numentities = r_refdef.scene.numentities;
3782 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3783 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3784 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3785 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3786 if (r_refdef.viewcache.maxentities < numentities)
3788 r_refdef.viewcache.maxentities = numentities;
3789 if (r_refdef.viewcache.entityvisible)
3790 Mem_Free(r_refdef.viewcache.entityvisible);
3791 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3793 if (r_refdef.viewcache.world_numclusters != numclusters)
3795 r_refdef.viewcache.world_numclusters = numclusters;
3796 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3797 if (r_refdef.viewcache.world_pvsbits)
3798 Mem_Free(r_refdef.viewcache.world_pvsbits);
3799 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3801 if (r_refdef.viewcache.world_numleafs != numleafs)
3803 r_refdef.viewcache.world_numleafs = numleafs;
3804 if (r_refdef.viewcache.world_leafvisible)
3805 Mem_Free(r_refdef.viewcache.world_leafvisible);
3806 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3808 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3810 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3811 if (r_refdef.viewcache.world_surfacevisible)
3812 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3813 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3817 extern rtexture_t *loadingscreentexture;
3818 void gl_main_start(void)
3820 loadingscreentexture = NULL;
3821 r_texture_blanknormalmap = NULL;
3822 r_texture_white = NULL;
3823 r_texture_grey128 = NULL;
3824 r_texture_black = NULL;
3825 r_texture_whitecube = NULL;
3826 r_texture_normalizationcube = NULL;
3827 r_texture_fogattenuation = NULL;
3828 r_texture_fogheighttexture = NULL;
3829 r_texture_gammaramps = NULL;
3830 r_texture_numcubemaps = 0;
3832 r_loaddds = r_texture_dds_load.integer != 0;
3833 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3835 switch(vid.renderpath)
3837 case RENDERPATH_GL20:
3838 case RENDERPATH_D3D9:
3839 case RENDERPATH_D3D10:
3840 case RENDERPATH_D3D11:
3841 case RENDERPATH_SOFT:
3842 case RENDERPATH_GLES2:
3843 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3844 Cvar_SetValueQuick(&gl_combine, 1);
3845 Cvar_SetValueQuick(&r_glsl, 1);
3846 r_loadnormalmap = true;
3850 case RENDERPATH_GL13:
3851 case RENDERPATH_GLES1:
3852 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3853 Cvar_SetValueQuick(&gl_combine, 1);
3854 Cvar_SetValueQuick(&r_glsl, 0);
3855 r_loadnormalmap = false;
3856 r_loadgloss = false;
3859 case RENDERPATH_GL11:
3860 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3861 Cvar_SetValueQuick(&gl_combine, 0);
3862 Cvar_SetValueQuick(&r_glsl, 0);
3863 r_loadnormalmap = false;
3864 r_loadgloss = false;
3870 R_FrameData_Reset();
3874 memset(r_queries, 0, sizeof(r_queries));
3876 r_qwskincache = NULL;
3877 r_qwskincache_size = 0;
3879 // due to caching of texture_t references, the collision cache must be reset
3880 Collision_Cache_Reset(true);
3882 // set up r_skinframe loading system for textures
3883 memset(&r_skinframe, 0, sizeof(r_skinframe));
3884 r_skinframe.loadsequence = 1;
3885 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3887 r_main_texturepool = R_AllocTexturePool();
3888 R_BuildBlankTextures();
3890 if (vid.support.arb_texture_cube_map)
3893 R_BuildNormalizationCube();
3895 r_texture_fogattenuation = NULL;
3896 r_texture_fogheighttexture = NULL;
3897 r_texture_gammaramps = NULL;
3898 //r_texture_fogintensity = NULL;
3899 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3900 memset(&r_waterstate, 0, sizeof(r_waterstate));
3901 r_glsl_permutation = NULL;
3902 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3903 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3904 glslshaderstring = NULL;
3906 r_hlsl_permutation = NULL;
3907 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3908 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3910 hlslshaderstring = NULL;
3911 memset(&r_svbsp, 0, sizeof (r_svbsp));
3913 r_refdef.fogmasktable_density = 0;
3916 void gl_main_shutdown(void)
3919 R_FrameData_Reset();
3921 R_Main_FreeViewCache();
3923 switch(vid.renderpath)
3925 case RENDERPATH_GL11:
3926 case RENDERPATH_GL13:
3927 case RENDERPATH_GL20:
3928 case RENDERPATH_GLES1:
3929 case RENDERPATH_GLES2:
3931 qglDeleteQueriesARB(r_maxqueries, r_queries);
3933 case RENDERPATH_D3D9:
3934 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3936 case RENDERPATH_D3D10:
3937 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3939 case RENDERPATH_D3D11:
3940 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3942 case RENDERPATH_SOFT:
3948 memset(r_queries, 0, sizeof(r_queries));
3950 r_qwskincache = NULL;
3951 r_qwskincache_size = 0;
3953 // clear out the r_skinframe state
3954 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3955 memset(&r_skinframe, 0, sizeof(r_skinframe));
3958 Mem_Free(r_svbsp.nodes);
3959 memset(&r_svbsp, 0, sizeof (r_svbsp));
3960 R_FreeTexturePool(&r_main_texturepool);
3961 loadingscreentexture = NULL;
3962 r_texture_blanknormalmap = NULL;
3963 r_texture_white = NULL;
3964 r_texture_grey128 = NULL;
3965 r_texture_black = NULL;
3966 r_texture_whitecube = NULL;
3967 r_texture_normalizationcube = NULL;
3968 r_texture_fogattenuation = NULL;
3969 r_texture_fogheighttexture = NULL;
3970 r_texture_gammaramps = NULL;
3971 r_texture_numcubemaps = 0;
3972 //r_texture_fogintensity = NULL;
3973 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3974 memset(&r_waterstate, 0, sizeof(r_waterstate));
3977 r_glsl_permutation = NULL;
3978 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3979 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3980 glslshaderstring = NULL;
3982 r_hlsl_permutation = NULL;
3983 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3984 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3986 hlslshaderstring = NULL;
3989 extern void CL_ParseEntityLump(char *entitystring);
3990 void gl_main_newmap(void)
3992 // FIXME: move this code to client
3993 char *entities, entname[MAX_QPATH];
3995 Mem_Free(r_qwskincache);
3996 r_qwskincache = NULL;
3997 r_qwskincache_size = 0;
4000 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4001 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4003 CL_ParseEntityLump(entities);
4007 if (cl.worldmodel->brush.entities)
4008 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4010 R_Main_FreeViewCache();
4012 R_FrameData_Reset();
4015 void GL_Main_Init(void)
4017 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4019 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4020 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4021 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4022 if (gamemode == GAME_NEHAHRA)
4024 Cvar_RegisterVariable (&gl_fogenable);
4025 Cvar_RegisterVariable (&gl_fogdensity);
4026 Cvar_RegisterVariable (&gl_fogred);
4027 Cvar_RegisterVariable (&gl_foggreen);
4028 Cvar_RegisterVariable (&gl_fogblue);
4029 Cvar_RegisterVariable (&gl_fogstart);
4030 Cvar_RegisterVariable (&gl_fogend);
4031 Cvar_RegisterVariable (&gl_skyclip);
4033 Cvar_RegisterVariable(&r_motionblur);
4034 Cvar_RegisterVariable(&r_motionblur_maxblur);
4035 Cvar_RegisterVariable(&r_motionblur_bmin);
4036 Cvar_RegisterVariable(&r_motionblur_vmin);
4037 Cvar_RegisterVariable(&r_motionblur_vmax);
4038 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4039 Cvar_RegisterVariable(&r_motionblur_randomize);
4040 Cvar_RegisterVariable(&r_damageblur);
4041 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4042 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4043 Cvar_RegisterVariable(&r_equalize_entities_by);
4044 Cvar_RegisterVariable(&r_equalize_entities_to);
4045 Cvar_RegisterVariable(&r_depthfirst);
4046 Cvar_RegisterVariable(&r_useinfinitefarclip);
4047 Cvar_RegisterVariable(&r_farclip_base);
4048 Cvar_RegisterVariable(&r_farclip_world);
4049 Cvar_RegisterVariable(&r_nearclip);
4050 Cvar_RegisterVariable(&r_deformvertexes);
4051 Cvar_RegisterVariable(&r_transparent);
4052 Cvar_RegisterVariable(&r_showoverdraw);
4053 Cvar_RegisterVariable(&r_showbboxes);
4054 Cvar_RegisterVariable(&r_showsurfaces);
4055 Cvar_RegisterVariable(&r_showtris);
4056 Cvar_RegisterVariable(&r_shownormals);
4057 Cvar_RegisterVariable(&r_showlighting);
4058 Cvar_RegisterVariable(&r_showshadowvolumes);
4059 Cvar_RegisterVariable(&r_showcollisionbrushes);
4060 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4061 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4062 Cvar_RegisterVariable(&r_showdisabledepthtest);
4063 Cvar_RegisterVariable(&r_drawportals);
4064 Cvar_RegisterVariable(&r_drawentities);
4065 Cvar_RegisterVariable(&r_draw2d);
4066 Cvar_RegisterVariable(&r_drawworld);
4067 Cvar_RegisterVariable(&r_cullentities_trace);
4068 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4069 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4070 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4071 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4072 Cvar_RegisterVariable(&r_drawviewmodel);
4073 Cvar_RegisterVariable(&r_drawexteriormodel);
4074 Cvar_RegisterVariable(&r_speeds);
4075 Cvar_RegisterVariable(&r_fullbrights);
4076 Cvar_RegisterVariable(&r_wateralpha);
4077 Cvar_RegisterVariable(&r_dynamic);
4078 Cvar_RegisterVariable(&r_fakelight);
4079 Cvar_RegisterVariable(&r_fakelight_intensity);
4080 Cvar_RegisterVariable(&r_fullbright);
4081 Cvar_RegisterVariable(&r_shadows);
4082 Cvar_RegisterVariable(&r_shadows_darken);
4083 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4084 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4085 Cvar_RegisterVariable(&r_shadows_throwdistance);
4086 Cvar_RegisterVariable(&r_shadows_throwdirection);
4087 Cvar_RegisterVariable(&r_shadows_focus);
4088 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4089 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4090 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4091 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4092 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4093 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4094 Cvar_RegisterVariable(&r_fog_exp2);
4095 Cvar_RegisterVariable(&r_fog_clear);
4096 Cvar_RegisterVariable(&r_drawfog);
4097 Cvar_RegisterVariable(&r_transparentdepthmasking);
4098 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4099 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4100 Cvar_RegisterVariable(&r_texture_dds_load);
4101 Cvar_RegisterVariable(&r_texture_dds_save);
4102 Cvar_RegisterVariable(&r_textureunits);
4103 Cvar_RegisterVariable(&gl_combine);
4104 Cvar_RegisterVariable(&r_viewfbo);
4105 Cvar_RegisterVariable(&r_viewscale);
4106 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4107 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4108 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4109 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4110 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4111 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4112 Cvar_RegisterVariable(&r_glsl);
4113 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4114 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4115 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4116 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4117 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4118 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4119 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4120 Cvar_RegisterVariable(&r_glsl_postprocess);
4121 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4122 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4123 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4124 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4125 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4126 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4127 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4128 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4130 Cvar_RegisterVariable(&r_water);
4131 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4132 Cvar_RegisterVariable(&r_water_clippingplanebias);
4133 Cvar_RegisterVariable(&r_water_refractdistort);
4134 Cvar_RegisterVariable(&r_water_reflectdistort);
4135 Cvar_RegisterVariable(&r_water_scissormode);
4136 Cvar_RegisterVariable(&r_lerpsprites);
4137 Cvar_RegisterVariable(&r_lerpmodels);
4138 Cvar_RegisterVariable(&r_lerplightstyles);
4139 Cvar_RegisterVariable(&r_waterscroll);
4140 Cvar_RegisterVariable(&r_bloom);
4141 Cvar_RegisterVariable(&r_bloom_colorscale);
4142 Cvar_RegisterVariable(&r_bloom_brighten);
4143 Cvar_RegisterVariable(&r_bloom_blur);
4144 Cvar_RegisterVariable(&r_bloom_resolution);
4145 Cvar_RegisterVariable(&r_bloom_colorexponent);
4146 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4147 Cvar_RegisterVariable(&r_hdr);
4148 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4149 Cvar_RegisterVariable(&r_hdr_glowintensity);
4150 Cvar_RegisterVariable(&r_hdr_range);
4151 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4152 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4153 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4154 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4155 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4156 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4157 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4158 Cvar_RegisterVariable(&developer_texturelogging);
4159 Cvar_RegisterVariable(&gl_lightmaps);
4160 Cvar_RegisterVariable(&r_test);
4161 Cvar_RegisterVariable(&r_glsl_saturation);
4162 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4163 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4164 Cvar_RegisterVariable(&r_framedatasize);
4165 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4166 Cvar_SetValue("r_fullbrights", 0);
4167 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4169 Cvar_RegisterVariable(&r_track_sprites);
4170 Cvar_RegisterVariable(&r_track_sprites_flags);
4171 Cvar_RegisterVariable(&r_track_sprites_scalew);
4172 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4173 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4174 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4175 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4176 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4179 extern void R_Textures_Init(void);
4180 extern void GL_Draw_Init(void);
4181 extern void GL_Main_Init(void);
4182 extern void R_Shadow_Init(void);
4183 extern void R_Sky_Init(void);
4184 extern void GL_Surf_Init(void);
4185 extern void R_Particles_Init(void);
4186 extern void R_Explosion_Init(void);
4187 extern void gl_backend_init(void);
4188 extern void Sbar_Init(void);
4189 extern void R_LightningBeams_Init(void);
4190 extern void Mod_RenderInit(void);
4191 extern void Font_Init(void);
4193 void Render_Init(void)
4206 R_LightningBeams_Init();
4215 extern char *ENGINE_EXTENSIONS;
4218 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4219 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4220 gl_version = (const char *)qglGetString(GL_VERSION);
4221 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4225 if (!gl_platformextensions)
4226 gl_platformextensions = "";
4228 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4229 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4230 Con_Printf("GL_VERSION: %s\n", gl_version);
4231 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4232 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4234 VID_CheckExtensions();
4236 // LordHavoc: report supported extensions
4237 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4239 // clear to black (loading plaque will be seen over this)
4240 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4243 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4247 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4249 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4252 p = r_refdef.view.frustum + i;
4257 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4261 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4265 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4269 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4273 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4277 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4281 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4285 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4293 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4297 for (i = 0;i < numplanes;i++)
4304 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4308 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4312 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4316 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4320 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4324 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4328 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4332 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4340 //==================================================================================
4342 // LordHavoc: this stores temporary data used within the same frame
4344 typedef struct r_framedata_mem_s
4346 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4347 size_t size; // how much usable space
4348 size_t current; // how much space in use
4349 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4350 size_t wantedsize; // how much space was allocated
4351 unsigned char *data; // start of real data (16byte aligned)
4355 static r_framedata_mem_t *r_framedata_mem;
4357 void R_FrameData_Reset(void)
4359 while (r_framedata_mem)
4361 r_framedata_mem_t *next = r_framedata_mem->purge;
4362 Mem_Free(r_framedata_mem);
4363 r_framedata_mem = next;
4367 void R_FrameData_Resize(void)
4370 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4371 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4372 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4374 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4375 newmem->wantedsize = wantedsize;
4376 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4377 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4378 newmem->current = 0;
4380 newmem->purge = r_framedata_mem;
4381 r_framedata_mem = newmem;
4385 void R_FrameData_NewFrame(void)
4387 R_FrameData_Resize();
4388 if (!r_framedata_mem)
4390 // if we ran out of space on the last frame, free the old memory now
4391 while (r_framedata_mem->purge)
4393 // repeatedly remove the second item in the list, leaving only head
4394 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4395 Mem_Free(r_framedata_mem->purge);
4396 r_framedata_mem->purge = next;
4398 // reset the current mem pointer
4399 r_framedata_mem->current = 0;
4400 r_framedata_mem->mark = 0;
4403 void *R_FrameData_Alloc(size_t size)
4407 // align to 16 byte boundary - the data pointer is already aligned, so we
4408 // only need to ensure the size of every allocation is also aligned
4409 size = (size + 15) & ~15;
4411 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4413 // emergency - we ran out of space, allocate more memory
4414 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4415 R_FrameData_Resize();
4418 data = r_framedata_mem->data + r_framedata_mem->current;
4419 r_framedata_mem->current += size;
4421 // count the usage for stats
4422 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4423 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4425 return (void *)data;
4428 void *R_FrameData_Store(size_t size, void *data)
4430 void *d = R_FrameData_Alloc(size);
4432 memcpy(d, data, size);
4436 void R_FrameData_SetMark(void)
4438 if (!r_framedata_mem)
4440 r_framedata_mem->mark = r_framedata_mem->current;
4443 void R_FrameData_ReturnToMark(void)
4445 if (!r_framedata_mem)
4447 r_framedata_mem->current = r_framedata_mem->mark;
4450 //==================================================================================
4452 // LordHavoc: animcache originally written by Echon, rewritten since then
4455 * Animation cache prevents re-generating mesh data for an animated model
4456 * multiple times in one frame for lighting, shadowing, reflections, etc.
4459 void R_AnimCache_Free(void)
4463 void R_AnimCache_ClearCache(void)
4466 entity_render_t *ent;
4468 for (i = 0;i < r_refdef.scene.numentities;i++)
4470 ent = r_refdef.scene.entities[i];
4471 ent->animcache_vertex3f = NULL;
4472 ent->animcache_normal3f = NULL;
4473 ent->animcache_svector3f = NULL;
4474 ent->animcache_tvector3f = NULL;
4475 ent->animcache_vertexmesh = NULL;
4476 ent->animcache_vertex3fbuffer = NULL;
4477 ent->animcache_vertexmeshbuffer = NULL;
4481 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4485 // check if we need the meshbuffers
4486 if (!vid.useinterleavedarrays)
4489 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4490 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4491 // TODO: upload vertex3f buffer?
4492 if (ent->animcache_vertexmesh)
4494 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4495 for (i = 0;i < numvertices;i++)
4496 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4497 if (ent->animcache_svector3f)
4498 for (i = 0;i < numvertices;i++)
4499 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4500 if (ent->animcache_tvector3f)
4501 for (i = 0;i < numvertices;i++)
4502 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4503 if (ent->animcache_normal3f)
4504 for (i = 0;i < numvertices;i++)
4505 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4506 // TODO: upload vertexmeshbuffer?
4510 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4512 dp_model_t *model = ent->model;
4514 // see if it's already cached this frame
4515 if (ent->animcache_vertex3f)
4517 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4518 if (wantnormals || wanttangents)
4520 if (ent->animcache_normal3f)
4521 wantnormals = false;
4522 if (ent->animcache_svector3f)
4523 wanttangents = false;
4524 if (wantnormals || wanttangents)
4526 numvertices = model->surfmesh.num_vertices;
4528 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4531 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4532 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4534 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4535 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4541 // see if this ent is worth caching
4542 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4544 // get some memory for this entity and generate mesh data
4545 numvertices = model->surfmesh.num_vertices;
4546 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4548 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4551 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4552 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4554 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4555 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4560 void R_AnimCache_CacheVisibleEntities(void)
4563 qboolean wantnormals = true;
4564 qboolean wanttangents = !r_showsurfaces.integer;
4566 switch(vid.renderpath)
4568 case RENDERPATH_GL20:
4569 case RENDERPATH_D3D9:
4570 case RENDERPATH_D3D10:
4571 case RENDERPATH_D3D11:
4572 case RENDERPATH_GLES2:
4574 case RENDERPATH_GL11:
4575 case RENDERPATH_GL13:
4576 case RENDERPATH_GLES1:
4577 wanttangents = false;
4579 case RENDERPATH_SOFT:
4583 if (r_shownormals.integer)
4584 wanttangents = wantnormals = true;
4586 // TODO: thread this
4587 // NOTE: R_PrepareRTLights() also caches entities
4589 for (i = 0;i < r_refdef.scene.numentities;i++)
4590 if (r_refdef.viewcache.entityvisible[i])
4591 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4594 //==================================================================================
4596 static void R_View_UpdateEntityLighting (void)
4599 entity_render_t *ent;
4600 vec3_t tempdiffusenormal, avg;
4601 vec_t f, fa, fd, fdd;
4602 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4604 for (i = 0;i < r_refdef.scene.numentities;i++)
4606 ent = r_refdef.scene.entities[i];
4608 // skip unseen models
4609 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4613 if (ent->model && ent->model->brush.num_leafs)
4615 // TODO: use modellight for r_ambient settings on world?
4616 VectorSet(ent->modellight_ambient, 0, 0, 0);
4617 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4618 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4622 // fetch the lighting from the worldmodel data
4623 VectorClear(ent->modellight_ambient);
4624 VectorClear(ent->modellight_diffuse);
4625 VectorClear(tempdiffusenormal);
4626 if (ent->flags & RENDER_LIGHT)
4629 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4631 // complete lightning for lit sprites
4632 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4633 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4635 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4636 org[2] = org[2] + r_overheadsprites_pushback.value;
4637 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4640 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4642 if(ent->flags & RENDER_EQUALIZE)
4644 // first fix up ambient lighting...
4645 if(r_equalize_entities_minambient.value > 0)
4647 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4650 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4651 if(fa < r_equalize_entities_minambient.value * fd)
4654 // fa'/fd' = minambient
4655 // fa'+0.25*fd' = fa+0.25*fd
4657 // fa' = fd' * minambient
4658 // fd'*(0.25+minambient) = fa+0.25*fd
4660 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4661 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4663 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4664 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
4665 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4666 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4671 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4673 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4674 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4678 // adjust brightness and saturation to target
4679 avg[0] = avg[1] = avg[2] = fa / f;
4680 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4681 avg[0] = avg[1] = avg[2] = fd / f;
4682 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4688 VectorSet(ent->modellight_ambient, 1, 1, 1);
4690 // move the light direction into modelspace coordinates for lighting code
4691 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4692 if(VectorLength2(ent->modellight_lightdir) == 0)
4693 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4694 VectorNormalize(ent->modellight_lightdir);
4698 #define MAX_LINEOFSIGHTTRACES 64
4700 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4703 vec3_t boxmins, boxmaxs;
4706 dp_model_t *model = r_refdef.scene.worldmodel;
4708 if (!model || !model->brush.TraceLineOfSight)
4711 // expand the box a little
4712 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4713 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4714 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4715 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4716 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4717 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4719 // return true if eye is inside enlarged box
4720 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4724 VectorCopy(eye, start);
4725 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4726 if (model->brush.TraceLineOfSight(model, start, end))
4729 // try various random positions
4730 for (i = 0;i < numsamples;i++)
4732 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4733 if (model->brush.TraceLineOfSight(model, start, end))
4741 static void R_View_UpdateEntityVisible (void)
4746 entity_render_t *ent;
4748 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4749 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4750 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4751 : RENDER_EXTERIORMODEL;
4752 if (!r_drawviewmodel.integer)
4753 renderimask |= RENDER_VIEWMODEL;
4754 if (!r_drawexteriormodel.integer)
4755 renderimask |= RENDER_EXTERIORMODEL;
4756 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4758 // worldmodel can check visibility
4759 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4760 for (i = 0;i < r_refdef.scene.numentities;i++)
4762 ent = r_refdef.scene.entities[i];
4763 if (!(ent->flags & renderimask))
4764 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)))
4765 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))
4766 r_refdef.viewcache.entityvisible[i] = true;
4771 // no worldmodel or it can't check visibility
4772 for (i = 0;i < r_refdef.scene.numentities;i++)
4774 ent = r_refdef.scene.entities[i];
4775 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));
4778 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4779 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4781 for (i = 0;i < r_refdef.scene.numentities;i++)
4783 if (!r_refdef.viewcache.entityvisible[i])
4785 ent = r_refdef.scene.entities[i];
4786 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4788 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4790 continue; // temp entities do pvs only
4791 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4792 ent->last_trace_visibility = realtime;
4793 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4794 r_refdef.viewcache.entityvisible[i] = 0;
4800 /// only used if skyrendermasked, and normally returns false
4801 int R_DrawBrushModelsSky (void)
4804 entity_render_t *ent;
4807 for (i = 0;i < r_refdef.scene.numentities;i++)
4809 if (!r_refdef.viewcache.entityvisible[i])
4811 ent = r_refdef.scene.entities[i];
4812 if (!ent->model || !ent->model->DrawSky)
4814 ent->model->DrawSky(ent);
4820 static void R_DrawNoModel(entity_render_t *ent);
4821 static void R_DrawModels(void)
4824 entity_render_t *ent;
4826 for (i = 0;i < r_refdef.scene.numentities;i++)
4828 if (!r_refdef.viewcache.entityvisible[i])
4830 ent = r_refdef.scene.entities[i];
4831 r_refdef.stats.entities++;
4833 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4836 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4837 Con_Printf("R_DrawModels\n");
4838 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]);
4839 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);
4840 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);
4843 if (ent->model && ent->model->Draw != NULL)
4844 ent->model->Draw(ent);
4850 static void R_DrawModelsDepth(void)
4853 entity_render_t *ent;
4855 for (i = 0;i < r_refdef.scene.numentities;i++)
4857 if (!r_refdef.viewcache.entityvisible[i])
4859 ent = r_refdef.scene.entities[i];
4860 if (ent->model && ent->model->DrawDepth != NULL)
4861 ent->model->DrawDepth(ent);
4865 static void R_DrawModelsDebug(void)
4868 entity_render_t *ent;
4870 for (i = 0;i < r_refdef.scene.numentities;i++)
4872 if (!r_refdef.viewcache.entityvisible[i])
4874 ent = r_refdef.scene.entities[i];
4875 if (ent->model && ent->model->DrawDebug != NULL)
4876 ent->model->DrawDebug(ent);
4880 static void R_DrawModelsAddWaterPlanes(void)
4883 entity_render_t *ent;
4885 for (i = 0;i < r_refdef.scene.numentities;i++)
4887 if (!r_refdef.viewcache.entityvisible[i])
4889 ent = r_refdef.scene.entities[i];
4890 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4891 ent->model->DrawAddWaterPlanes(ent);
4895 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4897 if (r_hdr_irisadaptation.integer)
4901 vec3_t diffusenormal;
4906 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4907 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4908 brightness = max(0.0000001f, brightness);
4909 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4910 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4911 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4912 current = r_hdr_irisadaptation_value.value;
4914 current = min(current + adjust, goal);
4915 else if (current > goal)
4916 current = max(current - adjust, goal);
4917 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4918 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4920 else if (r_hdr_irisadaptation_value.value != 1.0f)
4921 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4924 static void R_View_SetFrustum(const int *scissor)
4927 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4928 vec3_t forward, left, up, origin, v;
4932 // flipped x coordinates (because x points left here)
4933 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4934 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4936 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4937 switch(vid.renderpath)
4939 case RENDERPATH_D3D9:
4940 case RENDERPATH_D3D10:
4941 case RENDERPATH_D3D11:
4942 // non-flipped y coordinates
4943 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4944 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4946 case RENDERPATH_SOFT:
4947 case RENDERPATH_GL11:
4948 case RENDERPATH_GL13:
4949 case RENDERPATH_GL20:
4950 case RENDERPATH_GLES1:
4951 case RENDERPATH_GLES2:
4952 // non-flipped y coordinates
4953 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4954 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4959 // we can't trust r_refdef.view.forward and friends in reflected scenes
4960 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4963 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4964 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4965 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4966 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4967 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4968 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4969 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4970 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4971 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4972 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4973 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4974 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4978 zNear = r_refdef.nearclip;
4979 nudge = 1.0 - 1.0 / (1<<23);
4980 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4981 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4982 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4983 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4984 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4985 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4986 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4987 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4993 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4994 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4995 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4996 r_refdef.view.frustum[0].dist = m[15] - m[12];
4998 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4999 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5000 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5001 r_refdef.view.frustum[1].dist = m[15] + m[12];
5003 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5004 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5005 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5006 r_refdef.view.frustum[2].dist = m[15] - m[13];
5008 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5009 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5010 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5011 r_refdef.view.frustum[3].dist = m[15] + m[13];
5013 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5014 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5015 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5016 r_refdef.view.frustum[4].dist = m[15] - m[14];
5018 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5019 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5020 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5021 r_refdef.view.frustum[5].dist = m[15] + m[14];
5024 if (r_refdef.view.useperspective)
5026 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5027 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]);
5028 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]);
5029 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]);
5030 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]);
5032 // then the normals from the corners relative to origin
5033 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5034 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5035 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5036 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5038 // in a NORMAL view, forward cross left == up
5039 // in a REFLECTED view, forward cross left == down
5040 // so our cross products above need to be adjusted for a left handed coordinate system
5041 CrossProduct(forward, left, v);
5042 if(DotProduct(v, up) < 0)
5044 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5045 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5046 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5047 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5050 // Leaving those out was a mistake, those were in the old code, and they
5051 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5052 // I couldn't reproduce it after adding those normalizations. --blub
5053 VectorNormalize(r_refdef.view.frustum[0].normal);
5054 VectorNormalize(r_refdef.view.frustum[1].normal);
5055 VectorNormalize(r_refdef.view.frustum[2].normal);
5056 VectorNormalize(r_refdef.view.frustum[3].normal);
5058 // make the corners absolute
5059 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5060 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5061 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5062 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5065 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5067 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5068 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5069 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5070 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5071 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5075 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5076 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5077 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5078 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5079 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5080 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5081 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5082 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5083 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5084 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5086 r_refdef.view.numfrustumplanes = 5;
5088 if (r_refdef.view.useclipplane)
5090 r_refdef.view.numfrustumplanes = 6;
5091 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5094 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5095 PlaneClassify(r_refdef.view.frustum + i);
5097 // LordHavoc: note to all quake engine coders, Quake had a special case
5098 // for 90 degrees which assumed a square view (wrong), so I removed it,
5099 // Quake2 has it disabled as well.
5101 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5102 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5103 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5104 //PlaneClassify(&frustum[0]);
5106 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5107 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5108 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5109 //PlaneClassify(&frustum[1]);
5111 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5112 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5113 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5114 //PlaneClassify(&frustum[2]);
5116 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5117 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5118 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5119 //PlaneClassify(&frustum[3]);
5122 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5123 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5124 //PlaneClassify(&frustum[4]);
5127 void R_View_UpdateWithScissor(const int *myscissor)
5129 R_Main_ResizeViewCache();
5130 R_View_SetFrustum(myscissor);
5131 R_View_WorldVisibility(r_refdef.view.useclipplane);
5132 R_View_UpdateEntityVisible();
5133 R_View_UpdateEntityLighting();
5136 void R_View_Update(void)
5138 R_Main_ResizeViewCache();
5139 R_View_SetFrustum(NULL);
5140 R_View_WorldVisibility(r_refdef.view.useclipplane);
5141 R_View_UpdateEntityVisible();
5142 R_View_UpdateEntityLighting();
5145 float viewscalefpsadjusted = 1.0f;
5147 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5149 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5150 scale = bound(0.03125f, scale, 1.0f);
5151 *outwidth = (int)ceil(width * scale);
5152 *outheight = (int)ceil(height * scale);
5155 void R_Mesh_SetMainRenderTargets(void)
5157 if (r_bloomstate.fbo_framebuffer)
5158 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5160 R_Mesh_ResetRenderTargets();
5163 void R_SetupView(qboolean allowwaterclippingplane)
5165 const float *customclipplane = NULL;
5167 int scaledwidth, scaledheight;
5168 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5170 // LordHavoc: couldn't figure out how to make this approach the
5171 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5172 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5173 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5174 dist = r_refdef.view.clipplane.dist;
5175 plane[0] = r_refdef.view.clipplane.normal[0];
5176 plane[1] = r_refdef.view.clipplane.normal[1];
5177 plane[2] = r_refdef.view.clipplane.normal[2];
5179 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5182 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5183 if (!r_refdef.view.useperspective)
5184 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);
5185 else if (vid.stencil && r_useinfinitefarclip.integer)
5186 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);
5188 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);
5189 R_Mesh_SetMainRenderTargets();
5190 R_SetViewport(&r_refdef.view.viewport);
5191 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5193 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5194 float screenplane[4];
5195 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5196 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5197 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5198 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5199 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5203 void R_EntityMatrix(const matrix4x4_t *matrix)
5205 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5207 gl_modelmatrixchanged = false;
5208 gl_modelmatrix = *matrix;
5209 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5210 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5211 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5212 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5214 switch(vid.renderpath)
5216 case RENDERPATH_D3D9:
5218 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5219 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5222 case RENDERPATH_D3D10:
5223 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5225 case RENDERPATH_D3D11:
5226 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5228 case RENDERPATH_GL11:
5229 case RENDERPATH_GL13:
5230 case RENDERPATH_GLES1:
5231 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5233 case RENDERPATH_SOFT:
5234 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5235 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5237 case RENDERPATH_GL20:
5238 case RENDERPATH_GLES2:
5239 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5240 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5246 void R_ResetViewRendering2D(void)
5248 r_viewport_t viewport;
5251 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5252 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);
5253 R_Mesh_ResetRenderTargets();
5254 R_SetViewport(&viewport);
5255 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5256 GL_Color(1, 1, 1, 1);
5257 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5258 GL_BlendFunc(GL_ONE, GL_ZERO);
5259 GL_ScissorTest(false);
5260 GL_DepthMask(false);
5261 GL_DepthRange(0, 1);
5262 GL_DepthTest(false);
5263 GL_DepthFunc(GL_LEQUAL);
5264 R_EntityMatrix(&identitymatrix);
5265 R_Mesh_ResetTextureState();
5266 GL_PolygonOffset(0, 0);
5267 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5268 switch(vid.renderpath)
5270 case RENDERPATH_GL11:
5271 case RENDERPATH_GL13:
5272 case RENDERPATH_GL20:
5273 case RENDERPATH_GLES1:
5274 case RENDERPATH_GLES2:
5275 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5277 case RENDERPATH_D3D9:
5278 case RENDERPATH_D3D10:
5279 case RENDERPATH_D3D11:
5280 case RENDERPATH_SOFT:
5283 GL_CullFace(GL_NONE);
5286 void R_ResetViewRendering3D(void)
5291 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5292 GL_Color(1, 1, 1, 1);
5293 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5294 GL_BlendFunc(GL_ONE, GL_ZERO);
5295 GL_ScissorTest(true);
5297 GL_DepthRange(0, 1);
5299 GL_DepthFunc(GL_LEQUAL);
5300 R_EntityMatrix(&identitymatrix);
5301 R_Mesh_ResetTextureState();
5302 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5303 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5304 switch(vid.renderpath)
5306 case RENDERPATH_GL11:
5307 case RENDERPATH_GL13:
5308 case RENDERPATH_GL20:
5309 case RENDERPATH_GLES1:
5310 case RENDERPATH_GLES2:
5311 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5313 case RENDERPATH_D3D9:
5314 case RENDERPATH_D3D10:
5315 case RENDERPATH_D3D11:
5316 case RENDERPATH_SOFT:
5319 GL_CullFace(r_refdef.view.cullface_back);
5324 R_RenderView_UpdateViewVectors
5327 static void R_RenderView_UpdateViewVectors(void)
5329 // break apart the view matrix into vectors for various purposes
5330 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5331 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5332 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5333 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5334 // make an inverted copy of the view matrix for tracking sprites
5335 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5338 void R_RenderScene(void);
5339 void R_RenderWaterPlanes(void);
5341 static void R_Water_StartFrame(void)
5344 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5345 r_waterstate_waterplane_t *p;
5347 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5350 switch(vid.renderpath)
5352 case RENDERPATH_GL20:
5353 case RENDERPATH_D3D9:
5354 case RENDERPATH_D3D10:
5355 case RENDERPATH_D3D11:
5356 case RENDERPATH_SOFT:
5357 case RENDERPATH_GLES2:
5359 case RENDERPATH_GL11:
5360 case RENDERPATH_GL13:
5361 case RENDERPATH_GLES1:
5365 // set waterwidth and waterheight to the water resolution that will be
5366 // used (often less than the screen resolution for faster rendering)
5367 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5368 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5370 // calculate desired texture sizes
5371 // can't use water if the card does not support the texture size
5372 if (!r_water.integer || r_showsurfaces.integer)
5373 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5374 else if (vid.support.arb_texture_non_power_of_two)
5376 texturewidth = waterwidth;
5377 textureheight = waterheight;
5378 camerawidth = waterwidth;
5379 cameraheight = waterheight;
5383 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5384 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5385 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5386 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5389 // allocate textures as needed
5390 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5392 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5393 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5395 if (p->texture_refraction)
5396 R_FreeTexture(p->texture_refraction);
5397 p->texture_refraction = NULL;
5398 if (p->texture_reflection)
5399 R_FreeTexture(p->texture_reflection);
5400 p->texture_reflection = NULL;
5401 if (p->texture_camera)
5402 R_FreeTexture(p->texture_camera);
5403 p->texture_camera = NULL;
5405 memset(&r_waterstate, 0, sizeof(r_waterstate));
5406 r_waterstate.texturewidth = texturewidth;
5407 r_waterstate.textureheight = textureheight;
5408 r_waterstate.camerawidth = camerawidth;
5409 r_waterstate.cameraheight = cameraheight;
5412 if (r_waterstate.texturewidth)
5414 r_waterstate.enabled = true;
5416 // when doing a reduced render (HDR) we want to use a smaller area
5417 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5418 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5420 // set up variables that will be used in shader setup
5421 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5422 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5423 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5424 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5427 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5428 r_waterstate.numwaterplanes = 0;
5431 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5433 int triangleindex, planeindex;
5439 r_waterstate_waterplane_t *p;
5440 texture_t *t = R_GetCurrentTexture(surface->texture);
5442 // just use the first triangle with a valid normal for any decisions
5443 VectorClear(normal);
5444 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5446 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5447 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5448 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5449 TriangleNormal(vert[0], vert[1], vert[2], normal);
5450 if (VectorLength2(normal) >= 0.001)
5454 VectorCopy(normal, plane.normal);
5455 VectorNormalize(plane.normal);
5456 plane.dist = DotProduct(vert[0], plane.normal);
5457 PlaneClassify(&plane);
5458 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5460 // skip backfaces (except if nocullface is set)
5461 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5463 VectorNegate(plane.normal, plane.normal);
5465 PlaneClassify(&plane);
5469 // find a matching plane if there is one
5470 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5471 if(p->camera_entity == t->camera_entity)
5472 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5474 if (planeindex >= r_waterstate.maxwaterplanes)
5475 return; // nothing we can do, out of planes
5477 // if this triangle does not fit any known plane rendered this frame, add one
5478 if (planeindex >= r_waterstate.numwaterplanes)
5480 // store the new plane
5481 r_waterstate.numwaterplanes++;
5483 // clear materialflags and pvs
5484 p->materialflags = 0;
5485 p->pvsvalid = false;
5486 p->camera_entity = t->camera_entity;
5487 VectorCopy(surface->mins, p->mins);
5488 VectorCopy(surface->maxs, p->maxs);
5493 p->mins[0] = min(p->mins[0], surface->mins[0]);
5494 p->mins[1] = min(p->mins[1], surface->mins[1]);
5495 p->mins[2] = min(p->mins[2], surface->mins[2]);
5496 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5497 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5498 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5500 // merge this surface's materialflags into the waterplane
5501 p->materialflags |= t->currentmaterialflags;
5502 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5504 // merge this surface's PVS into the waterplane
5505 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5506 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5507 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5509 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5515 static void R_Water_ProcessPlanes(void)
5518 r_refdef_view_t originalview;
5519 r_refdef_view_t myview;
5521 r_waterstate_waterplane_t *p;
5524 originalview = r_refdef.view;
5526 // make sure enough textures are allocated
5527 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5529 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5531 if (!p->texture_refraction)
5532 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);
5533 if (!p->texture_refraction)
5536 else if (p->materialflags & MATERIALFLAG_CAMERA)
5538 if (!p->texture_camera)
5539 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);
5540 if (!p->texture_camera)
5544 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5546 if (!p->texture_reflection)
5547 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);
5548 if (!p->texture_reflection)
5554 r_refdef.view = originalview;
5555 r_refdef.view.showdebug = false;
5556 r_refdef.view.width = r_waterstate.waterwidth;
5557 r_refdef.view.height = r_waterstate.waterheight;
5558 r_refdef.view.useclipplane = true;
5559 myview = r_refdef.view;
5560 r_waterstate.renderingscene = true;
5561 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5563 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5565 r_refdef.view = myview;
5566 if(r_water_scissormode.integer)
5569 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5570 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5573 // render reflected scene and copy into texture
5574 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5575 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5576 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5577 r_refdef.view.clipplane = p->plane;
5579 // reverse the cullface settings for this render
5580 r_refdef.view.cullface_front = GL_FRONT;
5581 r_refdef.view.cullface_back = GL_BACK;
5582 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5584 r_refdef.view.usecustompvs = true;
5586 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5588 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5591 R_ResetViewRendering3D();
5592 R_ClearScreen(r_refdef.fogenabled);
5593 if(r_water_scissormode.integer & 2)
5594 R_View_UpdateWithScissor(myscissor);
5597 if(r_water_scissormode.integer & 1)
5598 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5601 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);
5604 // render the normal view scene and copy into texture
5605 // (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)
5606 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5608 r_refdef.view = myview;
5609 if(r_water_scissormode.integer)
5612 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5613 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5616 r_waterstate.renderingrefraction = true;
5618 r_refdef.view.clipplane = p->plane;
5619 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5620 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5622 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5624 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5625 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5626 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5627 R_RenderView_UpdateViewVectors();
5628 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5630 r_refdef.view.usecustompvs = true;
5631 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);
5635 PlaneClassify(&r_refdef.view.clipplane);
5637 R_ResetViewRendering3D();
5638 R_ClearScreen(r_refdef.fogenabled);
5639 if(r_water_scissormode.integer & 2)
5640 R_View_UpdateWithScissor(myscissor);
5643 if(r_water_scissormode.integer & 1)
5644 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5647 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);
5648 r_waterstate.renderingrefraction = false;
5650 else if (p->materialflags & MATERIALFLAG_CAMERA)
5652 r_refdef.view = myview;
5654 r_refdef.view.clipplane = p->plane;
5655 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5656 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5658 r_refdef.view.width = r_waterstate.camerawidth;
5659 r_refdef.view.height = r_waterstate.cameraheight;
5660 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5661 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5663 if(p->camera_entity)
5665 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5666 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5669 // note: all of the view is used for displaying... so
5670 // there is no use in scissoring
5672 // reverse the cullface settings for this render
5673 r_refdef.view.cullface_front = GL_FRONT;
5674 r_refdef.view.cullface_back = GL_BACK;
5675 // also reverse the view matrix
5676 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
5677 R_RenderView_UpdateViewVectors();
5678 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5680 r_refdef.view.usecustompvs = true;
5681 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);
5684 // camera needs no clipplane
5685 r_refdef.view.useclipplane = false;
5687 PlaneClassify(&r_refdef.view.clipplane);
5689 R_ResetViewRendering3D();
5690 R_ClearScreen(r_refdef.fogenabled);
5694 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);
5695 r_waterstate.renderingrefraction = false;
5699 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5700 r_waterstate.renderingscene = false;
5701 r_refdef.view = originalview;
5702 R_ResetViewRendering3D();
5703 R_ClearScreen(r_refdef.fogenabled);
5707 r_refdef.view = originalview;
5708 r_waterstate.renderingscene = false;
5709 Cvar_SetValueQuick(&r_water, 0);
5710 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5714 void R_Bloom_StartFrame(void)
5716 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5717 int viewwidth, viewheight;
5720 if (r_viewscale_fpsscaling.integer)
5722 double actualframetime;
5723 double targetframetime;
5725 actualframetime = r_refdef.lastdrawscreentime;
5726 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5727 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5728 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5729 if (r_viewscale_fpsscaling_stepsize.value > 0)
5730 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5731 viewscalefpsadjusted += adjust;
5732 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5735 viewscalefpsadjusted = 1.0f;
5737 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5739 switch(vid.renderpath)
5741 case RENDERPATH_GL20:
5742 case RENDERPATH_D3D9:
5743 case RENDERPATH_D3D10:
5744 case RENDERPATH_D3D11:
5745 case RENDERPATH_SOFT:
5746 case RENDERPATH_GLES2:
5748 case RENDERPATH_GL11:
5749 case RENDERPATH_GL13:
5750 case RENDERPATH_GLES1:
5754 // set bloomwidth and bloomheight to the bloom resolution that will be
5755 // used (often less than the screen resolution for faster rendering)
5756 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5757 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5758 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5759 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5760 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5762 // calculate desired texture sizes
5763 if (vid.support.arb_texture_non_power_of_two)
5765 screentexturewidth = vid.width;
5766 screentextureheight = vid.height;
5767 bloomtexturewidth = r_bloomstate.bloomwidth;
5768 bloomtextureheight = r_bloomstate.bloomheight;
5772 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5773 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5774 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5775 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5778 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))
5780 Cvar_SetValueQuick(&r_hdr, 0);
5781 Cvar_SetValueQuick(&r_bloom, 0);
5782 Cvar_SetValueQuick(&r_motionblur, 0);
5783 Cvar_SetValueQuick(&r_damageblur, 0);
5786 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)
5787 screentexturewidth = screentextureheight = 0;
5788 if (!r_hdr.integer && !r_bloom.integer)
5789 bloomtexturewidth = bloomtextureheight = 0;
5791 textype = TEXTYPE_COLORBUFFER;
5792 switch (vid.renderpath)
5794 case RENDERPATH_GL20:
5795 case RENDERPATH_GLES2:
5796 if (vid.support.ext_framebuffer_object)
5798 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5799 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5802 case RENDERPATH_GL11:
5803 case RENDERPATH_GL13:
5804 case RENDERPATH_GLES1:
5805 case RENDERPATH_D3D9:
5806 case RENDERPATH_D3D10:
5807 case RENDERPATH_D3D11:
5808 case RENDERPATH_SOFT:
5812 // allocate textures as needed
5813 if (r_bloomstate.screentexturewidth != screentexturewidth
5814 || r_bloomstate.screentextureheight != screentextureheight
5815 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5816 || r_bloomstate.bloomtextureheight != bloomtextureheight
5817 || r_bloomstate.texturetype != textype
5818 || r_bloomstate.viewfbo != r_viewfbo.integer)
5820 if (r_bloomstate.texture_bloom)
5821 R_FreeTexture(r_bloomstate.texture_bloom);
5822 r_bloomstate.texture_bloom = NULL;
5823 if (r_bloomstate.texture_screen)
5824 R_FreeTexture(r_bloomstate.texture_screen);
5825 r_bloomstate.texture_screen = NULL;
5826 if (r_bloomstate.fbo_framebuffer)
5827 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5828 r_bloomstate.fbo_framebuffer = 0;
5829 if (r_bloomstate.texture_framebuffercolor)
5830 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5831 r_bloomstate.texture_framebuffercolor = NULL;
5832 if (r_bloomstate.texture_framebufferdepth)
5833 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5834 r_bloomstate.texture_framebufferdepth = NULL;
5835 r_bloomstate.screentexturewidth = screentexturewidth;
5836 r_bloomstate.screentextureheight = screentextureheight;
5837 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5838 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);
5839 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5841 // FIXME: choose depth bits based on a cvar
5842 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5843 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);
5844 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5845 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5846 // render depth into one texture and normalmap into the other
5850 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5851 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5852 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5853 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5854 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5857 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5858 r_bloomstate.bloomtextureheight = bloomtextureheight;
5859 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5860 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);
5861 r_bloomstate.viewfbo = r_viewfbo.integer;
5862 r_bloomstate.texturetype = textype;
5865 // when doing a reduced render (HDR) we want to use a smaller area
5866 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5867 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5868 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5869 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5870 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5872 // set up a texcoord array for the full resolution screen image
5873 // (we have to keep this around to copy back during final render)
5874 r_bloomstate.screentexcoord2f[0] = 0;
5875 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5876 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5877 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5878 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5879 r_bloomstate.screentexcoord2f[5] = 0;
5880 r_bloomstate.screentexcoord2f[6] = 0;
5881 r_bloomstate.screentexcoord2f[7] = 0;
5883 // set up a texcoord array for the reduced resolution bloom image
5884 // (which will be additive blended over the screen image)
5885 r_bloomstate.bloomtexcoord2f[0] = 0;
5886 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5887 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5888 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5889 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5890 r_bloomstate.bloomtexcoord2f[5] = 0;
5891 r_bloomstate.bloomtexcoord2f[6] = 0;
5892 r_bloomstate.bloomtexcoord2f[7] = 0;
5894 switch(vid.renderpath)
5896 case RENDERPATH_GL11:
5897 case RENDERPATH_GL13:
5898 case RENDERPATH_GL20:
5899 case RENDERPATH_SOFT:
5900 case RENDERPATH_GLES1:
5901 case RENDERPATH_GLES2:
5903 case RENDERPATH_D3D9:
5904 case RENDERPATH_D3D10:
5905 case RENDERPATH_D3D11:
5908 for (i = 0;i < 4;i++)
5910 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5911 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5912 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5913 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5919 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5921 r_bloomstate.enabled = true;
5922 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5925 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);
5927 if (r_bloomstate.fbo_framebuffer)
5928 r_refdef.view.clear = true;
5931 void R_Bloom_CopyBloomTexture(float colorscale)
5933 r_refdef.stats.bloom++;
5935 // scale down screen texture to the bloom texture size
5937 R_Mesh_SetMainRenderTargets();
5938 R_SetViewport(&r_bloomstate.viewport);
5939 GL_BlendFunc(GL_ONE, GL_ZERO);
5940 GL_Color(colorscale, colorscale, colorscale, 1);
5941 // 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...
5942 switch(vid.renderpath)
5944 case RENDERPATH_GL11:
5945 case RENDERPATH_GL13:
5946 case RENDERPATH_GL20:
5947 case RENDERPATH_GLES1:
5948 case RENDERPATH_GLES2:
5949 case RENDERPATH_SOFT:
5950 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5952 case RENDERPATH_D3D9:
5953 case RENDERPATH_D3D10:
5954 case RENDERPATH_D3D11:
5955 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5958 // TODO: do boxfilter scale-down in shader?
5959 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5960 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5961 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5963 // we now have a bloom image in the framebuffer
5964 // copy it into the bloom image texture for later processing
5965 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);
5966 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5969 void R_Bloom_CopyHDRTexture(void)
5971 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);
5972 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5975 void R_Bloom_MakeTexture(void)
5978 float xoffset, yoffset, r, brighten;
5980 r_refdef.stats.bloom++;
5982 R_ResetViewRendering2D();
5984 // we have a bloom image in the framebuffer
5986 R_SetViewport(&r_bloomstate.viewport);
5988 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5991 r = bound(0, r_bloom_colorexponent.value / x, 1);
5992 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5994 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5995 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5996 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5997 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5999 // copy the vertically blurred bloom view to a texture
6000 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);
6001 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6004 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6005 brighten = r_bloom_brighten.value;
6006 if (r_bloomstate.hdr)
6007 brighten *= r_hdr_range.value;
6008 brighten = sqrt(brighten);
6010 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6011 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6013 for (dir = 0;dir < 2;dir++)
6015 // blend on at multiple vertical offsets to achieve a vertical blur
6016 // TODO: do offset blends using GLSL
6017 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6018 GL_BlendFunc(GL_ONE, GL_ZERO);
6019 for (x = -range;x <= range;x++)
6021 if (!dir){xoffset = 0;yoffset = x;}
6022 else {xoffset = x;yoffset = 0;}
6023 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6024 yoffset /= (float)r_bloomstate.bloomtextureheight;
6025 // compute a texcoord array with the specified x and y offset
6026 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6027 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6028 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6029 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6030 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6031 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6032 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6033 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6034 // this r value looks like a 'dot' particle, fading sharply to
6035 // black at the edges
6036 // (probably not realistic but looks good enough)
6037 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6038 //r = brighten/(range*2+1);
6039 r = brighten / (range * 2 + 1);
6041 r *= (1 - x*x/(float)(range*range));
6042 GL_Color(r, r, r, 1);
6043 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6044 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6045 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6046 GL_BlendFunc(GL_ONE, GL_ONE);
6049 // copy the vertically blurred bloom view to a texture
6050 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);
6051 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6055 void R_HDR_RenderBloomTexture(void)
6057 int oldwidth, oldheight;
6058 float oldcolorscale;
6059 qboolean oldwaterstate;
6061 oldwaterstate = r_waterstate.enabled;
6062 oldcolorscale = r_refdef.view.colorscale;
6063 oldwidth = r_refdef.view.width;
6064 oldheight = r_refdef.view.height;
6065 r_refdef.view.width = r_bloomstate.bloomwidth;
6066 r_refdef.view.height = r_bloomstate.bloomheight;
6068 if(r_hdr.integer < 2)
6069 r_waterstate.enabled = false;
6071 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6072 // TODO: add exposure compensation features
6073 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6075 r_refdef.view.showdebug = false;
6076 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6078 R_ResetViewRendering3D();
6080 R_ClearScreen(r_refdef.fogenabled);
6081 if (r_timereport_active)
6082 R_TimeReport("HDRclear");
6085 if (r_timereport_active)
6086 R_TimeReport("visibility");
6088 // only do secondary renders with HDR if r_hdr is 2 or higher
6089 r_waterstate.numwaterplanes = 0;
6090 if (r_waterstate.enabled)
6091 R_RenderWaterPlanes();
6093 r_refdef.view.showdebug = true;
6095 r_waterstate.numwaterplanes = 0;
6097 R_ResetViewRendering2D();
6099 R_Bloom_CopyHDRTexture();
6100 R_Bloom_MakeTexture();
6102 // restore the view settings
6103 r_waterstate.enabled = oldwaterstate;
6104 r_refdef.view.width = oldwidth;
6105 r_refdef.view.height = oldheight;
6106 r_refdef.view.colorscale = oldcolorscale;
6108 R_ResetViewRendering3D();
6110 R_ClearScreen(r_refdef.fogenabled);
6111 if (r_timereport_active)
6112 R_TimeReport("viewclear");
6115 static void R_BlendView(void)
6117 unsigned int permutation;
6118 float uservecs[4][4];
6120 switch (vid.renderpath)
6122 case RENDERPATH_GL20:
6123 case RENDERPATH_D3D9:
6124 case RENDERPATH_D3D10:
6125 case RENDERPATH_D3D11:
6126 case RENDERPATH_SOFT:
6127 case RENDERPATH_GLES2:
6129 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6130 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6131 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6132 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6133 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6135 if (r_bloomstate.texture_screen)
6137 // make sure the buffer is available
6138 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6140 R_ResetViewRendering2D();
6141 R_Mesh_SetMainRenderTargets();
6143 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6145 // declare variables
6147 static float avgspeed;
6149 speed = VectorLength(cl.movement_velocity);
6151 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6152 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6154 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6155 speed = bound(0, speed, 1);
6156 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6158 // calculate values into a standard alpha
6159 cl.motionbluralpha = 1 - exp(-
6161 (r_motionblur.value * speed / 80)
6163 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6166 max(0.0001, cl.time - cl.oldtime) // fps independent
6169 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6170 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6172 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6174 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6175 GL_Color(1, 1, 1, cl.motionbluralpha);
6176 switch(vid.renderpath)
6178 case RENDERPATH_GL11:
6179 case RENDERPATH_GL13:
6180 case RENDERPATH_GL20:
6181 case RENDERPATH_GLES1:
6182 case RENDERPATH_GLES2:
6183 case RENDERPATH_SOFT:
6184 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6186 case RENDERPATH_D3D9:
6187 case RENDERPATH_D3D10:
6188 case RENDERPATH_D3D11:
6189 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6192 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6193 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6194 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6198 // copy view into the screen texture
6199 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);
6200 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6202 else if (!r_bloomstate.texture_bloom)
6204 // we may still have to do view tint...
6205 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6207 // apply a color tint to the whole view
6208 R_ResetViewRendering2D();
6209 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6210 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6211 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6212 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6213 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6215 break; // no screen processing, no bloom, skip it
6218 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6220 // render simple bloom effect
6221 // copy the screen and shrink it and darken it for the bloom process
6222 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6223 // make the bloom texture
6224 R_Bloom_MakeTexture();
6227 #if _MSC_VER >= 1400
6228 #define sscanf sscanf_s
6230 memset(uservecs, 0, sizeof(uservecs));
6231 if (r_glsl_postprocess_uservec1_enable.integer)
6232 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6233 if (r_glsl_postprocess_uservec2_enable.integer)
6234 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6235 if (r_glsl_postprocess_uservec3_enable.integer)
6236 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6237 if (r_glsl_postprocess_uservec4_enable.integer)
6238 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6240 R_ResetViewRendering2D();
6241 GL_Color(1, 1, 1, 1);
6242 GL_BlendFunc(GL_ONE, GL_ZERO);
6244 switch(vid.renderpath)
6246 case RENDERPATH_GL20:
6247 case RENDERPATH_GLES2:
6248 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6249 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6250 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6251 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6252 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6253 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]);
6254 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6255 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]);
6256 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]);
6257 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]);
6258 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]);
6259 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6260 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6261 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);
6263 case RENDERPATH_D3D9:
6265 // 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...
6266 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6267 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6268 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6269 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6270 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6271 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6272 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6273 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6274 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6275 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6276 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6277 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6278 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6279 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6282 case RENDERPATH_D3D10:
6283 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6285 case RENDERPATH_D3D11:
6286 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6288 case RENDERPATH_SOFT:
6289 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6290 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6291 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6292 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6293 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6294 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6295 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6296 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6297 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6298 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6299 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6300 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6301 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6302 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6307 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6308 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6310 case RENDERPATH_GL11:
6311 case RENDERPATH_GL13:
6312 case RENDERPATH_GLES1:
6313 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6315 // apply a color tint to the whole view
6316 R_ResetViewRendering2D();
6317 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6318 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6319 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6320 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6321 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6327 matrix4x4_t r_waterscrollmatrix;
6329 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6331 if (r_refdef.fog_density)
6333 r_refdef.fogcolor[0] = r_refdef.fog_red;
6334 r_refdef.fogcolor[1] = r_refdef.fog_green;
6335 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6337 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6338 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6339 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6340 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6344 VectorCopy(r_refdef.fogcolor, fogvec);
6345 // color.rgb *= ContrastBoost * SceneBrightness;
6346 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6347 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6348 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6349 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6354 void R_UpdateVariables(void)
6358 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6360 r_refdef.farclip = r_farclip_base.value;
6361 if (r_refdef.scene.worldmodel)
6362 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6363 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6365 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6366 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6367 r_refdef.polygonfactor = 0;
6368 r_refdef.polygonoffset = 0;
6369 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6370 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6372 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6373 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6374 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6375 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6376 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6377 if (FAKELIGHT_ENABLED)
6379 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6381 if (r_showsurfaces.integer)
6383 r_refdef.scene.rtworld = false;
6384 r_refdef.scene.rtworldshadows = false;
6385 r_refdef.scene.rtdlight = false;
6386 r_refdef.scene.rtdlightshadows = false;
6387 r_refdef.lightmapintensity = 0;
6390 if (gamemode == GAME_NEHAHRA)
6392 if (gl_fogenable.integer)
6394 r_refdef.oldgl_fogenable = true;
6395 r_refdef.fog_density = gl_fogdensity.value;
6396 r_refdef.fog_red = gl_fogred.value;
6397 r_refdef.fog_green = gl_foggreen.value;
6398 r_refdef.fog_blue = gl_fogblue.value;
6399 r_refdef.fog_alpha = 1;
6400 r_refdef.fog_start = 0;
6401 r_refdef.fog_end = gl_skyclip.value;
6402 r_refdef.fog_height = 1<<30;
6403 r_refdef.fog_fadedepth = 128;
6405 else if (r_refdef.oldgl_fogenable)
6407 r_refdef.oldgl_fogenable = false;
6408 r_refdef.fog_density = 0;
6409 r_refdef.fog_red = 0;
6410 r_refdef.fog_green = 0;
6411 r_refdef.fog_blue = 0;
6412 r_refdef.fog_alpha = 0;
6413 r_refdef.fog_start = 0;
6414 r_refdef.fog_end = 0;
6415 r_refdef.fog_height = 1<<30;
6416 r_refdef.fog_fadedepth = 128;
6420 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6421 r_refdef.fog_start = max(0, r_refdef.fog_start);
6422 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6424 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6426 if (r_refdef.fog_density && r_drawfog.integer)
6428 r_refdef.fogenabled = true;
6429 // this is the point where the fog reaches 0.9986 alpha, which we
6430 // consider a good enough cutoff point for the texture
6431 // (0.9986 * 256 == 255.6)
6432 if (r_fog_exp2.integer)
6433 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6435 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6436 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6437 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6438 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6439 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6440 R_BuildFogHeightTexture();
6441 // fog color was already set
6442 // update the fog texture
6443 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)
6444 R_BuildFogTexture();
6445 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6446 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6449 r_refdef.fogenabled = false;
6451 switch(vid.renderpath)
6453 case RENDERPATH_GL20:
6454 case RENDERPATH_D3D9:
6455 case RENDERPATH_D3D10:
6456 case RENDERPATH_D3D11:
6457 case RENDERPATH_SOFT:
6458 case RENDERPATH_GLES2:
6459 if(v_glslgamma.integer && !vid_gammatables_trivial)
6461 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6463 // build GLSL gamma texture
6464 #define RAMPWIDTH 256
6465 unsigned short ramp[RAMPWIDTH * 3];
6466 unsigned char rampbgr[RAMPWIDTH][4];
6469 r_texture_gammaramps_serial = vid_gammatables_serial;
6471 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6472 for(i = 0; i < RAMPWIDTH; ++i)
6474 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6475 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6476 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6479 if (r_texture_gammaramps)
6481 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6485 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6491 // remove GLSL gamma texture
6494 case RENDERPATH_GL11:
6495 case RENDERPATH_GL13:
6496 case RENDERPATH_GLES1:
6501 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6502 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6508 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6509 if( scenetype != r_currentscenetype ) {
6510 // store the old scenetype
6511 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6512 r_currentscenetype = scenetype;
6513 // move in the new scene
6514 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6523 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6525 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6526 if( scenetype == r_currentscenetype ) {
6527 return &r_refdef.scene;
6529 return &r_scenes_store[ scenetype ];
6538 int dpsoftrast_test;
6539 void R_RenderView(void)
6541 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6543 dpsoftrast_test = r_test.integer;
6545 if (r_timereport_active)
6546 R_TimeReport("start");
6547 r_textureframe++; // used only by R_GetCurrentTexture
6548 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6550 if(R_CompileShader_CheckStaticParms())
6553 if (!r_drawentities.integer)
6554 r_refdef.scene.numentities = 0;
6556 R_AnimCache_ClearCache();
6557 R_FrameData_NewFrame();
6559 /* adjust for stereo display */
6560 if(R_Stereo_Active())
6562 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);
6563 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6566 if (r_refdef.view.isoverlay)
6568 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6569 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6570 R_TimeReport("depthclear");
6572 r_refdef.view.showdebug = false;
6574 r_waterstate.enabled = false;
6575 r_waterstate.numwaterplanes = 0;
6579 r_refdef.view.matrix = originalmatrix;
6585 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6587 r_refdef.view.matrix = originalmatrix;
6588 return; //Host_Error ("R_RenderView: NULL worldmodel");
6591 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6593 R_RenderView_UpdateViewVectors();
6595 R_Shadow_UpdateWorldLightSelection();
6597 R_Bloom_StartFrame();
6598 R_Water_StartFrame();
6601 if (r_timereport_active)
6602 R_TimeReport("viewsetup");
6604 R_ResetViewRendering3D();
6606 if (r_refdef.view.clear || r_refdef.fogenabled)
6608 R_ClearScreen(r_refdef.fogenabled);
6609 if (r_timereport_active)
6610 R_TimeReport("viewclear");
6612 r_refdef.view.clear = true;
6614 // this produces a bloom texture to be used in R_BlendView() later
6615 if (r_bloomstate.hdr)
6617 R_HDR_RenderBloomTexture();
6618 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6619 r_textureframe++; // used only by R_GetCurrentTexture
6622 r_refdef.view.showdebug = true;
6625 if (r_timereport_active)
6626 R_TimeReport("visibility");
6628 r_waterstate.numwaterplanes = 0;
6629 if (r_waterstate.enabled)
6630 R_RenderWaterPlanes();
6633 r_waterstate.numwaterplanes = 0;
6636 if (r_timereport_active)
6637 R_TimeReport("blendview");
6639 GL_Scissor(0, 0, vid.width, vid.height);
6640 GL_ScissorTest(false);
6642 r_refdef.view.matrix = originalmatrix;
6647 void R_RenderWaterPlanes(void)
6649 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6651 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6652 if (r_timereport_active)
6653 R_TimeReport("waterworld");
6656 // don't let sound skip if going slow
6657 if (r_refdef.scene.extraupdate)
6660 R_DrawModelsAddWaterPlanes();
6661 if (r_timereport_active)
6662 R_TimeReport("watermodels");
6664 if (r_waterstate.numwaterplanes)
6666 R_Water_ProcessPlanes();
6667 if (r_timereport_active)
6668 R_TimeReport("waterscenes");
6672 extern void R_DrawLightningBeams (void);
6673 extern void VM_CL_AddPolygonsToMeshQueue (void);
6674 extern void R_DrawPortals (void);
6675 extern cvar_t cl_locs_show;
6676 static void R_DrawLocs(void);
6677 static void R_DrawEntityBBoxes(void);
6678 static void R_DrawModelDecals(void);
6679 extern void R_DrawModelShadows(void);
6680 extern void R_DrawModelShadowMaps(void);
6681 extern cvar_t cl_decals_newsystem;
6682 extern qboolean r_shadow_usingdeferredprepass;
6683 void R_RenderScene(void)
6685 qboolean shadowmapping = false;
6687 if (r_timereport_active)
6688 R_TimeReport("beginscene");
6690 r_refdef.stats.renders++;
6694 // don't let sound skip if going slow
6695 if (r_refdef.scene.extraupdate)
6698 R_MeshQueue_BeginScene();
6702 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);
6704 if (r_timereport_active)
6705 R_TimeReport("skystartframe");
6707 if (cl.csqc_vidvars.drawworld)
6709 // don't let sound skip if going slow
6710 if (r_refdef.scene.extraupdate)
6713 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6715 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6716 if (r_timereport_active)
6717 R_TimeReport("worldsky");
6720 if (R_DrawBrushModelsSky() && r_timereport_active)
6721 R_TimeReport("bmodelsky");
6723 if (skyrendermasked && skyrenderlater)
6725 // we have to force off the water clipping plane while rendering sky
6729 if (r_timereport_active)
6730 R_TimeReport("sky");
6734 R_AnimCache_CacheVisibleEntities();
6735 if (r_timereport_active)
6736 R_TimeReport("animation");
6738 R_Shadow_PrepareLights();
6739 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6740 R_Shadow_PrepareModelShadows();
6741 if (r_timereport_active)
6742 R_TimeReport("preparelights");
6744 if (R_Shadow_ShadowMappingEnabled())
6745 shadowmapping = true;
6747 if (r_shadow_usingdeferredprepass)
6748 R_Shadow_DrawPrepass();
6750 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6752 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6753 if (r_timereport_active)
6754 R_TimeReport("worlddepth");
6756 if (r_depthfirst.integer >= 2)
6758 R_DrawModelsDepth();
6759 if (r_timereport_active)
6760 R_TimeReport("modeldepth");
6763 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6765 R_DrawModelShadowMaps();
6766 R_ResetViewRendering3D();
6767 // don't let sound skip if going slow
6768 if (r_refdef.scene.extraupdate)
6772 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6774 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6775 if (r_timereport_active)
6776 R_TimeReport("world");
6779 // don't let sound skip if going slow
6780 if (r_refdef.scene.extraupdate)
6784 if (r_timereport_active)
6785 R_TimeReport("models");
6787 // don't let sound skip if going slow
6788 if (r_refdef.scene.extraupdate)
6791 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6793 R_DrawModelShadows();
6794 R_ResetViewRendering3D();
6795 // don't let sound skip if going slow
6796 if (r_refdef.scene.extraupdate)
6800 if (!r_shadow_usingdeferredprepass)
6802 R_Shadow_DrawLights();
6803 if (r_timereport_active)
6804 R_TimeReport("rtlights");
6807 // don't let sound skip if going slow
6808 if (r_refdef.scene.extraupdate)
6811 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6813 R_DrawModelShadows();
6814 R_ResetViewRendering3D();
6815 // don't let sound skip if going slow
6816 if (r_refdef.scene.extraupdate)
6820 if (cl.csqc_vidvars.drawworld)
6822 if (cl_decals_newsystem.integer)
6824 R_DrawModelDecals();
6825 if (r_timereport_active)
6826 R_TimeReport("modeldecals");
6831 if (r_timereport_active)
6832 R_TimeReport("decals");
6836 if (r_timereport_active)
6837 R_TimeReport("particles");
6840 if (r_timereport_active)
6841 R_TimeReport("explosions");
6843 R_DrawLightningBeams();
6844 if (r_timereport_active)
6845 R_TimeReport("lightning");
6848 VM_CL_AddPolygonsToMeshQueue();
6850 if (r_refdef.view.showdebug)
6852 if (cl_locs_show.integer)
6855 if (r_timereport_active)
6856 R_TimeReport("showlocs");
6859 if (r_drawportals.integer)
6862 if (r_timereport_active)
6863 R_TimeReport("portals");
6866 if (r_showbboxes.value > 0)
6868 R_DrawEntityBBoxes();
6869 if (r_timereport_active)
6870 R_TimeReport("bboxes");
6874 if (r_transparent.integer)
6876 R_MeshQueue_RenderTransparent();
6877 if (r_timereport_active)
6878 R_TimeReport("drawtrans");
6881 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))
6883 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6884 if (r_timereport_active)
6885 R_TimeReport("worlddebug");
6886 R_DrawModelsDebug();
6887 if (r_timereport_active)
6888 R_TimeReport("modeldebug");
6891 if (cl.csqc_vidvars.drawworld)
6893 R_Shadow_DrawCoronas();
6894 if (r_timereport_active)
6895 R_TimeReport("coronas");
6900 GL_DepthTest(false);
6901 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6902 GL_Color(1, 1, 1, 1);
6903 qglBegin(GL_POLYGON);
6904 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6905 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6906 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6907 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6909 qglBegin(GL_POLYGON);
6910 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]);
6911 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]);
6912 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]);
6913 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]);
6915 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6919 // don't let sound skip if going slow
6920 if (r_refdef.scene.extraupdate)
6923 R_ResetViewRendering2D();
6926 static const unsigned short bboxelements[36] =
6936 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6939 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6941 RSurf_ActiveWorldEntity();
6943 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6944 GL_DepthMask(false);
6945 GL_DepthRange(0, 1);
6946 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6947 // R_Mesh_ResetTextureState();
6949 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6950 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6951 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6952 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6953 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6954 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6955 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6956 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6957 R_FillColors(color4f, 8, cr, cg, cb, ca);
6958 if (r_refdef.fogenabled)
6960 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6962 f1 = RSurf_FogVertex(v);
6964 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6965 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6966 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6969 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6970 R_Mesh_ResetTextureState();
6971 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6972 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6975 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6979 prvm_edict_t *edict;
6980 prvm_prog_t *prog_save = prog;
6982 // this function draws bounding boxes of server entities
6986 GL_CullFace(GL_NONE);
6987 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6991 for (i = 0;i < numsurfaces;i++)
6993 edict = PRVM_EDICT_NUM(surfacelist[i]);
6994 switch ((int)edict->fields.server->solid)
6996 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6997 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6998 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6999 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7000 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7001 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7003 color[3] *= r_showbboxes.value;
7004 color[3] = bound(0, color[3], 1);
7005 GL_DepthTest(!r_showdisabledepthtest.integer);
7006 GL_CullFace(r_refdef.view.cullface_front);
7007 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7013 static void R_DrawEntityBBoxes(void)
7016 prvm_edict_t *edict;
7018 prvm_prog_t *prog_save = prog;
7020 // this function draws bounding boxes of server entities
7026 for (i = 0;i < prog->num_edicts;i++)
7028 edict = PRVM_EDICT_NUM(i);
7029 if (edict->priv.server->free)
7031 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7032 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7034 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7036 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7037 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7043 static const int nomodelelement3i[24] =
7055 static const unsigned short nomodelelement3s[24] =
7067 static const float nomodelvertex3f[6*3] =
7077 static const float nomodelcolor4f[6*4] =
7079 0.0f, 0.0f, 0.5f, 1.0f,
7080 0.0f, 0.0f, 0.5f, 1.0f,
7081 0.0f, 0.5f, 0.0f, 1.0f,
7082 0.0f, 0.5f, 0.0f, 1.0f,
7083 0.5f, 0.0f, 0.0f, 1.0f,
7084 0.5f, 0.0f, 0.0f, 1.0f
7087 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7093 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);
7095 // this is only called once per entity so numsurfaces is always 1, and
7096 // surfacelist is always {0}, so this code does not handle batches
7098 if (rsurface.ent_flags & RENDER_ADDITIVE)
7100 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7101 GL_DepthMask(false);
7103 else if (rsurface.colormod[3] < 1)
7105 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7106 GL_DepthMask(false);
7110 GL_BlendFunc(GL_ONE, GL_ZERO);
7113 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7114 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7115 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7116 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7117 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7118 for (i = 0, c = color4f;i < 6;i++, c += 4)
7120 c[0] *= rsurface.colormod[0];
7121 c[1] *= rsurface.colormod[1];
7122 c[2] *= rsurface.colormod[2];
7123 c[3] *= rsurface.colormod[3];
7125 if (r_refdef.fogenabled)
7127 for (i = 0, c = color4f;i < 6;i++, c += 4)
7129 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7131 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7132 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7133 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7136 // R_Mesh_ResetTextureState();
7137 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7138 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7139 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7142 void R_DrawNoModel(entity_render_t *ent)
7145 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7146 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7147 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7149 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7152 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7154 vec3_t right1, right2, diff, normal;
7156 VectorSubtract (org2, org1, normal);
7158 // calculate 'right' vector for start
7159 VectorSubtract (r_refdef.view.origin, org1, diff);
7160 CrossProduct (normal, diff, right1);
7161 VectorNormalize (right1);
7163 // calculate 'right' vector for end
7164 VectorSubtract (r_refdef.view.origin, org2, diff);
7165 CrossProduct (normal, diff, right2);
7166 VectorNormalize (right2);
7168 vert[ 0] = org1[0] + width * right1[0];
7169 vert[ 1] = org1[1] + width * right1[1];
7170 vert[ 2] = org1[2] + width * right1[2];
7171 vert[ 3] = org1[0] - width * right1[0];
7172 vert[ 4] = org1[1] - width * right1[1];
7173 vert[ 5] = org1[2] - width * right1[2];
7174 vert[ 6] = org2[0] - width * right2[0];
7175 vert[ 7] = org2[1] - width * right2[1];
7176 vert[ 8] = org2[2] - width * right2[2];
7177 vert[ 9] = org2[0] + width * right2[0];
7178 vert[10] = org2[1] + width * right2[1];
7179 vert[11] = org2[2] + width * right2[2];
7182 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)
7184 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7185 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7186 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7187 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7188 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7189 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7190 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7191 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7192 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7193 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7194 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7195 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7198 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7203 VectorSet(v, x, y, z);
7204 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7205 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7207 if (i == mesh->numvertices)
7209 if (mesh->numvertices < mesh->maxvertices)
7211 VectorCopy(v, vertex3f);
7212 mesh->numvertices++;
7214 return mesh->numvertices;
7220 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7224 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7225 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7226 e = mesh->element3i + mesh->numtriangles * 3;
7227 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7229 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7230 if (mesh->numtriangles < mesh->maxtriangles)
7235 mesh->numtriangles++;
7237 element[1] = element[2];
7241 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7245 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7246 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7247 e = mesh->element3i + mesh->numtriangles * 3;
7248 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7250 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7251 if (mesh->numtriangles < mesh->maxtriangles)
7256 mesh->numtriangles++;
7258 element[1] = element[2];
7262 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7263 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7265 int planenum, planenum2;
7268 mplane_t *plane, *plane2;
7270 double temppoints[2][256*3];
7271 // figure out how large a bounding box we need to properly compute this brush
7273 for (w = 0;w < numplanes;w++)
7274 maxdist = max(maxdist, fabs(planes[w].dist));
7275 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7276 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7277 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7281 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7282 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7284 if (planenum2 == planenum)
7286 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);
7289 if (tempnumpoints < 3)
7291 // generate elements forming a triangle fan for this polygon
7292 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7296 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)
7298 texturelayer_t *layer;
7299 layer = t->currentlayers + t->currentnumlayers++;
7301 layer->depthmask = depthmask;
7302 layer->blendfunc1 = blendfunc1;
7303 layer->blendfunc2 = blendfunc2;
7304 layer->texture = texture;
7305 layer->texmatrix = *matrix;
7306 layer->color[0] = r;
7307 layer->color[1] = g;
7308 layer->color[2] = b;
7309 layer->color[3] = a;
7312 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7314 if(parms[0] == 0 && parms[1] == 0)
7316 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7317 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7322 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7325 index = parms[2] + r_refdef.scene.time * parms[3];
7326 index -= floor(index);
7327 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7330 case Q3WAVEFUNC_NONE:
7331 case Q3WAVEFUNC_NOISE:
7332 case Q3WAVEFUNC_COUNT:
7335 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7336 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7337 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7338 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7339 case Q3WAVEFUNC_TRIANGLE:
7341 f = index - floor(index);
7352 f = parms[0] + parms[1] * f;
7353 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7354 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7358 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7363 matrix4x4_t matrix, temp;
7364 switch(tcmod->tcmod)
7368 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7369 matrix = r_waterscrollmatrix;
7371 matrix = identitymatrix;
7373 case Q3TCMOD_ENTITYTRANSLATE:
7374 // this is used in Q3 to allow the gamecode to control texcoord
7375 // scrolling on the entity, which is not supported in darkplaces yet.
7376 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7378 case Q3TCMOD_ROTATE:
7379 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7380 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7381 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7384 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7386 case Q3TCMOD_SCROLL:
7387 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7389 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7390 w = (int) tcmod->parms[0];
7391 h = (int) tcmod->parms[1];
7392 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7394 idx = (int) floor(f * w * h);
7395 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7397 case Q3TCMOD_STRETCH:
7398 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7399 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7401 case Q3TCMOD_TRANSFORM:
7402 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7403 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7404 VectorSet(tcmat + 6, 0 , 0 , 1);
7405 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7406 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7408 case Q3TCMOD_TURBULENT:
7409 // this is handled in the RSurf_PrepareVertices function
7410 matrix = identitymatrix;
7414 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7417 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7419 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7420 char name[MAX_QPATH];
7421 skinframe_t *skinframe;
7422 unsigned char pixels[296*194];
7423 strlcpy(cache->name, skinname, sizeof(cache->name));
7424 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7425 if (developer_loading.integer)
7426 Con_Printf("loading %s\n", name);
7427 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7428 if (!skinframe || !skinframe->base)
7431 fs_offset_t filesize;
7433 f = FS_LoadFile(name, tempmempool, true, &filesize);
7436 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7437 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7441 cache->skinframe = skinframe;
7444 texture_t *R_GetCurrentTexture(texture_t *t)
7447 const entity_render_t *ent = rsurface.entity;
7448 dp_model_t *model = ent->model;
7449 q3shaderinfo_layer_tcmod_t *tcmod;
7451 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7452 return t->currentframe;
7453 t->update_lastrenderframe = r_textureframe;
7454 t->update_lastrenderentity = (void *)ent;
7456 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7457 t->camera_entity = ent->entitynumber;
7459 t->camera_entity = 0;
7461 // switch to an alternate material if this is a q1bsp animated material
7463 texture_t *texture = t;
7464 int s = rsurface.ent_skinnum;
7465 if ((unsigned int)s >= (unsigned int)model->numskins)
7467 if (model->skinscenes)
7469 if (model->skinscenes[s].framecount > 1)
7470 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7472 s = model->skinscenes[s].firstframe;
7475 t = t + s * model->num_surfaces;
7478 // use an alternate animation if the entity's frame is not 0,
7479 // and only if the texture has an alternate animation
7480 if (rsurface.ent_alttextures && t->anim_total[1])
7481 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7483 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7485 texture->currentframe = t;
7488 // update currentskinframe to be a qw skin or animation frame
7489 if (rsurface.ent_qwskin >= 0)
7491 i = rsurface.ent_qwskin;
7492 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7494 r_qwskincache_size = cl.maxclients;
7496 Mem_Free(r_qwskincache);
7497 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7499 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7500 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7501 t->currentskinframe = r_qwskincache[i].skinframe;
7502 if (t->currentskinframe == NULL)
7503 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7505 else if (t->numskinframes >= 2)
7506 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7507 if (t->backgroundnumskinframes >= 2)
7508 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7510 t->currentmaterialflags = t->basematerialflags;
7511 t->currentalpha = rsurface.colormod[3];
7512 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7513 t->currentalpha *= r_wateralpha.value;
7514 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7515 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7516 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7517 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7518 if (!(rsurface.ent_flags & RENDER_LIGHT))
7519 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7520 else if (FAKELIGHT_ENABLED)
7522 // no modellight if using fakelight for the map
7524 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7526 // pick a model lighting mode
7527 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7528 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7530 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7532 if (rsurface.ent_flags & RENDER_ADDITIVE)
7533 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7534 else if (t->currentalpha < 1)
7535 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7536 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7537 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7538 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7539 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7540 if (t->backgroundnumskinframes)
7541 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7542 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7544 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7545 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7548 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7549 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7550 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7552 // there is no tcmod
7553 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7555 t->currenttexmatrix = r_waterscrollmatrix;
7556 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7558 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7560 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7561 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7564 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7565 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7566 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7567 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7569 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7570 if (t->currentskinframe->qpixels)
7571 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7572 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7573 if (!t->basetexture)
7574 t->basetexture = r_texture_notexture;
7575 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7576 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7577 t->nmaptexture = t->currentskinframe->nmap;
7578 if (!t->nmaptexture)
7579 t->nmaptexture = r_texture_blanknormalmap;
7580 t->glosstexture = r_texture_black;
7581 t->glowtexture = t->currentskinframe->glow;
7582 t->fogtexture = t->currentskinframe->fog;
7583 t->reflectmasktexture = t->currentskinframe->reflect;
7584 if (t->backgroundnumskinframes)
7586 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7587 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7588 t->backgroundglosstexture = r_texture_black;
7589 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7590 if (!t->backgroundnmaptexture)
7591 t->backgroundnmaptexture = r_texture_blanknormalmap;
7595 t->backgroundbasetexture = r_texture_white;
7596 t->backgroundnmaptexture = r_texture_blanknormalmap;
7597 t->backgroundglosstexture = r_texture_black;
7598 t->backgroundglowtexture = NULL;
7600 t->specularpower = r_shadow_glossexponent.value;
7601 // TODO: store reference values for these in the texture?
7602 t->specularscale = 0;
7603 if (r_shadow_gloss.integer > 0)
7605 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7607 if (r_shadow_glossintensity.value > 0)
7609 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7610 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7611 t->specularscale = r_shadow_glossintensity.value;
7614 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7616 t->glosstexture = r_texture_white;
7617 t->backgroundglosstexture = r_texture_white;
7618 t->specularscale = r_shadow_gloss2intensity.value;
7619 t->specularpower = r_shadow_gloss2exponent.value;
7622 t->specularscale *= t->specularscalemod;
7623 t->specularpower *= t->specularpowermod;
7625 // lightmaps mode looks bad with dlights using actual texturing, so turn
7626 // off the colormap and glossmap, but leave the normalmap on as it still
7627 // accurately represents the shading involved
7628 if (gl_lightmaps.integer)
7630 t->basetexture = r_texture_grey128;
7631 t->pantstexture = r_texture_black;
7632 t->shirttexture = r_texture_black;
7633 t->nmaptexture = r_texture_blanknormalmap;
7634 t->glosstexture = r_texture_black;
7635 t->glowtexture = NULL;
7636 t->fogtexture = NULL;
7637 t->reflectmasktexture = NULL;
7638 t->backgroundbasetexture = NULL;
7639 t->backgroundnmaptexture = r_texture_blanknormalmap;
7640 t->backgroundglosstexture = r_texture_black;
7641 t->backgroundglowtexture = NULL;
7642 t->specularscale = 0;
7643 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7646 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7647 VectorClear(t->dlightcolor);
7648 t->currentnumlayers = 0;
7649 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7651 int blendfunc1, blendfunc2;
7653 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7655 blendfunc1 = GL_SRC_ALPHA;
7656 blendfunc2 = GL_ONE;
7658 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7660 blendfunc1 = GL_SRC_ALPHA;
7661 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7663 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7665 blendfunc1 = t->customblendfunc[0];
7666 blendfunc2 = t->customblendfunc[1];
7670 blendfunc1 = GL_ONE;
7671 blendfunc2 = GL_ZERO;
7673 // don't colormod evilblend textures
7674 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7675 VectorSet(t->lightmapcolor, 1, 1, 1);
7676 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7677 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7679 // fullbright is not affected by r_refdef.lightmapintensity
7680 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]);
7681 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7682 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]);
7683 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7684 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]);
7688 vec3_t ambientcolor;
7690 // set the color tint used for lights affecting this surface
7691 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7693 // q3bsp has no lightmap updates, so the lightstylevalue that
7694 // would normally be baked into the lightmap must be
7695 // applied to the color
7696 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7697 if (model->type == mod_brushq3)
7698 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7699 colorscale *= r_refdef.lightmapintensity;
7700 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7701 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7702 // basic lit geometry
7703 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]);
7704 // add pants/shirt if needed
7705 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7706 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]);
7707 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7708 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]);
7709 // now add ambient passes if needed
7710 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7712 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]);
7713 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7714 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]);
7715 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7716 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]);
7719 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7720 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]);
7721 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7723 // if this is opaque use alpha blend which will darken the earlier
7726 // if this is an alpha blended material, all the earlier passes
7727 // were darkened by fog already, so we only need to add the fog
7728 // color ontop through the fog mask texture
7730 // if this is an additive blended material, all the earlier passes
7731 // were darkened by fog already, and we should not add fog color
7732 // (because the background was not darkened, there is no fog color
7733 // that was lost behind it).
7734 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]);
7738 return t->currentframe;
7741 rsurfacestate_t rsurface;
7743 void RSurf_ActiveWorldEntity(void)
7745 dp_model_t *model = r_refdef.scene.worldmodel;
7746 //if (rsurface.entity == r_refdef.scene.worldentity)
7748 rsurface.entity = r_refdef.scene.worldentity;
7749 rsurface.skeleton = NULL;
7750 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7751 rsurface.ent_skinnum = 0;
7752 rsurface.ent_qwskin = -1;
7753 rsurface.ent_shadertime = 0;
7754 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7755 rsurface.matrix = identitymatrix;
7756 rsurface.inversematrix = identitymatrix;
7757 rsurface.matrixscale = 1;
7758 rsurface.inversematrixscale = 1;
7759 R_EntityMatrix(&identitymatrix);
7760 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7761 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7762 rsurface.fograngerecip = r_refdef.fograngerecip;
7763 rsurface.fogheightfade = r_refdef.fogheightfade;
7764 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7765 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7766 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7767 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7768 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7769 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7770 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7771 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7772 rsurface.colormod[3] = 1;
7773 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);
7774 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7775 rsurface.frameblend[0].lerp = 1;
7776 rsurface.ent_alttextures = false;
7777 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7778 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7779 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7780 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7781 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7782 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7783 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7784 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7785 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7786 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7787 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7788 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7789 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7790 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7791 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7792 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7793 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7794 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7795 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7796 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7797 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7798 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7799 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7800 rsurface.modelelement3i = model->surfmesh.data_element3i;
7801 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7802 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7803 rsurface.modelelement3s = model->surfmesh.data_element3s;
7804 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7805 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7806 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7807 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7808 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7809 rsurface.modelsurfaces = model->data_surfaces;
7810 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7811 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7812 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7813 rsurface.modelgeneratedvertex = false;
7814 rsurface.batchgeneratedvertex = false;
7815 rsurface.batchfirstvertex = 0;
7816 rsurface.batchnumvertices = 0;
7817 rsurface.batchfirsttriangle = 0;
7818 rsurface.batchnumtriangles = 0;
7819 rsurface.batchvertex3f = NULL;
7820 rsurface.batchvertex3f_vertexbuffer = NULL;
7821 rsurface.batchvertex3f_bufferoffset = 0;
7822 rsurface.batchsvector3f = NULL;
7823 rsurface.batchsvector3f_vertexbuffer = NULL;
7824 rsurface.batchsvector3f_bufferoffset = 0;
7825 rsurface.batchtvector3f = NULL;
7826 rsurface.batchtvector3f_vertexbuffer = NULL;
7827 rsurface.batchtvector3f_bufferoffset = 0;
7828 rsurface.batchnormal3f = NULL;
7829 rsurface.batchnormal3f_vertexbuffer = NULL;
7830 rsurface.batchnormal3f_bufferoffset = 0;
7831 rsurface.batchlightmapcolor4f = NULL;
7832 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7833 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7834 rsurface.batchtexcoordtexture2f = NULL;
7835 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7836 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7837 rsurface.batchtexcoordlightmap2f = NULL;
7838 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7839 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7840 rsurface.batchvertexmesh = NULL;
7841 rsurface.batchvertexmeshbuffer = NULL;
7842 rsurface.batchvertex3fbuffer = NULL;
7843 rsurface.batchelement3i = NULL;
7844 rsurface.batchelement3i_indexbuffer = NULL;
7845 rsurface.batchelement3i_bufferoffset = 0;
7846 rsurface.batchelement3s = NULL;
7847 rsurface.batchelement3s_indexbuffer = NULL;
7848 rsurface.batchelement3s_bufferoffset = 0;
7849 rsurface.passcolor4f = NULL;
7850 rsurface.passcolor4f_vertexbuffer = NULL;
7851 rsurface.passcolor4f_bufferoffset = 0;
7854 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7856 dp_model_t *model = ent->model;
7857 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7859 rsurface.entity = (entity_render_t *)ent;
7860 rsurface.skeleton = ent->skeleton;
7861 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7862 rsurface.ent_skinnum = ent->skinnum;
7863 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;
7864 rsurface.ent_shadertime = ent->shadertime;
7865 rsurface.ent_flags = ent->flags;
7866 rsurface.matrix = ent->matrix;
7867 rsurface.inversematrix = ent->inversematrix;
7868 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7869 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7870 R_EntityMatrix(&rsurface.matrix);
7871 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7872 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7873 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7874 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7875 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7876 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7877 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7878 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7879 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7880 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7881 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7882 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7883 rsurface.colormod[3] = ent->alpha;
7884 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7885 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7886 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7887 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7888 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7889 if (ent->model->brush.submodel && !prepass)
7891 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7892 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7894 if (model->surfmesh.isanimated && model->AnimateVertices)
7896 if (ent->animcache_vertex3f)
7898 rsurface.modelvertex3f = ent->animcache_vertex3f;
7899 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7900 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7901 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7902 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7903 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7904 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7906 else if (wanttangents)
7908 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7909 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7910 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7911 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7912 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7913 rsurface.modelvertexmesh = NULL;
7914 rsurface.modelvertexmeshbuffer = NULL;
7915 rsurface.modelvertex3fbuffer = NULL;
7917 else if (wantnormals)
7919 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7920 rsurface.modelsvector3f = NULL;
7921 rsurface.modeltvector3f = NULL;
7922 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7923 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7924 rsurface.modelvertexmesh = NULL;
7925 rsurface.modelvertexmeshbuffer = NULL;
7926 rsurface.modelvertex3fbuffer = NULL;
7930 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7931 rsurface.modelsvector3f = NULL;
7932 rsurface.modeltvector3f = NULL;
7933 rsurface.modelnormal3f = NULL;
7934 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7935 rsurface.modelvertexmesh = NULL;
7936 rsurface.modelvertexmeshbuffer = NULL;
7937 rsurface.modelvertex3fbuffer = NULL;
7939 rsurface.modelvertex3f_vertexbuffer = 0;
7940 rsurface.modelvertex3f_bufferoffset = 0;
7941 rsurface.modelsvector3f_vertexbuffer = 0;
7942 rsurface.modelsvector3f_bufferoffset = 0;
7943 rsurface.modeltvector3f_vertexbuffer = 0;
7944 rsurface.modeltvector3f_bufferoffset = 0;
7945 rsurface.modelnormal3f_vertexbuffer = 0;
7946 rsurface.modelnormal3f_bufferoffset = 0;
7947 rsurface.modelgeneratedvertex = true;
7951 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7952 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7953 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7954 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7955 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7956 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7957 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7958 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7959 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7960 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7961 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7962 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7963 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7964 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7965 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7966 rsurface.modelgeneratedvertex = false;
7968 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7969 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7970 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7971 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7972 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7973 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7974 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7975 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7976 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7977 rsurface.modelelement3i = model->surfmesh.data_element3i;
7978 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7979 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7980 rsurface.modelelement3s = model->surfmesh.data_element3s;
7981 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7982 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7983 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7984 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7985 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7986 rsurface.modelsurfaces = model->data_surfaces;
7987 rsurface.batchgeneratedvertex = false;
7988 rsurface.batchfirstvertex = 0;
7989 rsurface.batchnumvertices = 0;
7990 rsurface.batchfirsttriangle = 0;
7991 rsurface.batchnumtriangles = 0;
7992 rsurface.batchvertex3f = NULL;
7993 rsurface.batchvertex3f_vertexbuffer = NULL;
7994 rsurface.batchvertex3f_bufferoffset = 0;
7995 rsurface.batchsvector3f = NULL;
7996 rsurface.batchsvector3f_vertexbuffer = NULL;
7997 rsurface.batchsvector3f_bufferoffset = 0;
7998 rsurface.batchtvector3f = NULL;
7999 rsurface.batchtvector3f_vertexbuffer = NULL;
8000 rsurface.batchtvector3f_bufferoffset = 0;
8001 rsurface.batchnormal3f = NULL;
8002 rsurface.batchnormal3f_vertexbuffer = NULL;
8003 rsurface.batchnormal3f_bufferoffset = 0;
8004 rsurface.batchlightmapcolor4f = NULL;
8005 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8006 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8007 rsurface.batchtexcoordtexture2f = NULL;
8008 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8009 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8010 rsurface.batchtexcoordlightmap2f = NULL;
8011 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8012 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8013 rsurface.batchvertexmesh = NULL;
8014 rsurface.batchvertexmeshbuffer = NULL;
8015 rsurface.batchvertex3fbuffer = NULL;
8016 rsurface.batchelement3i = NULL;
8017 rsurface.batchelement3i_indexbuffer = NULL;
8018 rsurface.batchelement3i_bufferoffset = 0;
8019 rsurface.batchelement3s = NULL;
8020 rsurface.batchelement3s_indexbuffer = NULL;
8021 rsurface.batchelement3s_bufferoffset = 0;
8022 rsurface.passcolor4f = NULL;
8023 rsurface.passcolor4f_vertexbuffer = NULL;
8024 rsurface.passcolor4f_bufferoffset = 0;
8027 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)
8029 rsurface.entity = r_refdef.scene.worldentity;
8030 rsurface.skeleton = NULL;
8031 rsurface.ent_skinnum = 0;
8032 rsurface.ent_qwskin = -1;
8033 rsurface.ent_shadertime = shadertime;
8034 rsurface.ent_flags = entflags;
8035 rsurface.modelnumvertices = numvertices;
8036 rsurface.modelnumtriangles = numtriangles;
8037 rsurface.matrix = *matrix;
8038 rsurface.inversematrix = *inversematrix;
8039 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8040 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8041 R_EntityMatrix(&rsurface.matrix);
8042 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8043 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8044 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8045 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8046 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8047 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8048 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8049 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8050 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8051 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8052 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8053 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8054 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);
8055 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8056 rsurface.frameblend[0].lerp = 1;
8057 rsurface.ent_alttextures = false;
8058 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8059 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8062 rsurface.modelvertex3f = (float *)vertex3f;
8063 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8064 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8065 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8067 else if (wantnormals)
8069 rsurface.modelvertex3f = (float *)vertex3f;
8070 rsurface.modelsvector3f = NULL;
8071 rsurface.modeltvector3f = NULL;
8072 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8076 rsurface.modelvertex3f = (float *)vertex3f;
8077 rsurface.modelsvector3f = NULL;
8078 rsurface.modeltvector3f = NULL;
8079 rsurface.modelnormal3f = NULL;
8081 rsurface.modelvertexmesh = NULL;
8082 rsurface.modelvertexmeshbuffer = NULL;
8083 rsurface.modelvertex3fbuffer = NULL;
8084 rsurface.modelvertex3f_vertexbuffer = 0;
8085 rsurface.modelvertex3f_bufferoffset = 0;
8086 rsurface.modelsvector3f_vertexbuffer = 0;
8087 rsurface.modelsvector3f_bufferoffset = 0;
8088 rsurface.modeltvector3f_vertexbuffer = 0;
8089 rsurface.modeltvector3f_bufferoffset = 0;
8090 rsurface.modelnormal3f_vertexbuffer = 0;
8091 rsurface.modelnormal3f_bufferoffset = 0;
8092 rsurface.modelgeneratedvertex = true;
8093 rsurface.modellightmapcolor4f = (float *)color4f;
8094 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8095 rsurface.modellightmapcolor4f_bufferoffset = 0;
8096 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8097 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8098 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8099 rsurface.modeltexcoordlightmap2f = NULL;
8100 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8101 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8102 rsurface.modelelement3i = (int *)element3i;
8103 rsurface.modelelement3i_indexbuffer = NULL;
8104 rsurface.modelelement3i_bufferoffset = 0;
8105 rsurface.modelelement3s = (unsigned short *)element3s;
8106 rsurface.modelelement3s_indexbuffer = NULL;
8107 rsurface.modelelement3s_bufferoffset = 0;
8108 rsurface.modellightmapoffsets = NULL;
8109 rsurface.modelsurfaces = NULL;
8110 rsurface.batchgeneratedvertex = false;
8111 rsurface.batchfirstvertex = 0;
8112 rsurface.batchnumvertices = 0;
8113 rsurface.batchfirsttriangle = 0;
8114 rsurface.batchnumtriangles = 0;
8115 rsurface.batchvertex3f = NULL;
8116 rsurface.batchvertex3f_vertexbuffer = NULL;
8117 rsurface.batchvertex3f_bufferoffset = 0;
8118 rsurface.batchsvector3f = NULL;
8119 rsurface.batchsvector3f_vertexbuffer = NULL;
8120 rsurface.batchsvector3f_bufferoffset = 0;
8121 rsurface.batchtvector3f = NULL;
8122 rsurface.batchtvector3f_vertexbuffer = NULL;
8123 rsurface.batchtvector3f_bufferoffset = 0;
8124 rsurface.batchnormal3f = NULL;
8125 rsurface.batchnormal3f_vertexbuffer = NULL;
8126 rsurface.batchnormal3f_bufferoffset = 0;
8127 rsurface.batchlightmapcolor4f = NULL;
8128 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8129 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8130 rsurface.batchtexcoordtexture2f = NULL;
8131 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8132 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8133 rsurface.batchtexcoordlightmap2f = NULL;
8134 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8135 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8136 rsurface.batchvertexmesh = NULL;
8137 rsurface.batchvertexmeshbuffer = NULL;
8138 rsurface.batchvertex3fbuffer = NULL;
8139 rsurface.batchelement3i = NULL;
8140 rsurface.batchelement3i_indexbuffer = NULL;
8141 rsurface.batchelement3i_bufferoffset = 0;
8142 rsurface.batchelement3s = NULL;
8143 rsurface.batchelement3s_indexbuffer = NULL;
8144 rsurface.batchelement3s_bufferoffset = 0;
8145 rsurface.passcolor4f = NULL;
8146 rsurface.passcolor4f_vertexbuffer = NULL;
8147 rsurface.passcolor4f_bufferoffset = 0;
8149 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8151 if ((wantnormals || wanttangents) && !normal3f)
8153 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8154 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8156 if (wanttangents && !svector3f)
8158 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8159 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8160 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8165 float RSurf_FogPoint(const float *v)
8167 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8168 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8169 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8170 float FogHeightFade = r_refdef.fogheightfade;
8172 unsigned int fogmasktableindex;
8173 if (r_refdef.fogplaneviewabove)
8174 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8176 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8177 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8178 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8181 float RSurf_FogVertex(const float *v)
8183 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8184 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8185 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8186 float FogHeightFade = rsurface.fogheightfade;
8188 unsigned int fogmasktableindex;
8189 if (r_refdef.fogplaneviewabove)
8190 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8192 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8193 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8194 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8197 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8200 for (i = 0;i < numelements;i++)
8201 outelement3i[i] = inelement3i[i] + adjust;
8204 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8205 extern cvar_t gl_vbo;
8206 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8214 int surfacefirsttriangle;
8215 int surfacenumtriangles;
8216 int surfacefirstvertex;
8217 int surfaceendvertex;
8218 int surfacenumvertices;
8219 int batchnumvertices;
8220 int batchnumtriangles;
8224 qboolean dynamicvertex;
8228 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8230 q3shaderinfo_deform_t *deform;
8231 const msurface_t *surface, *firstsurface;
8232 r_vertexmesh_t *vertexmesh;
8233 if (!texturenumsurfaces)
8235 // find vertex range of this surface batch
8237 firstsurface = texturesurfacelist[0];
8238 firsttriangle = firstsurface->num_firsttriangle;
8239 batchnumvertices = 0;
8240 batchnumtriangles = 0;
8241 firstvertex = endvertex = firstsurface->num_firstvertex;
8242 for (i = 0;i < texturenumsurfaces;i++)
8244 surface = texturesurfacelist[i];
8245 if (surface != firstsurface + i)
8247 surfacefirstvertex = surface->num_firstvertex;
8248 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8249 surfacenumvertices = surface->num_vertices;
8250 surfacenumtriangles = surface->num_triangles;
8251 if (firstvertex > surfacefirstvertex)
8252 firstvertex = surfacefirstvertex;
8253 if (endvertex < surfaceendvertex)
8254 endvertex = surfaceendvertex;
8255 batchnumvertices += surfacenumvertices;
8256 batchnumtriangles += surfacenumtriangles;
8259 // we now know the vertex range used, and if there are any gaps in it
8260 rsurface.batchfirstvertex = firstvertex;
8261 rsurface.batchnumvertices = endvertex - firstvertex;
8262 rsurface.batchfirsttriangle = firsttriangle;
8263 rsurface.batchnumtriangles = batchnumtriangles;
8265 // this variable holds flags for which properties have been updated that
8266 // may require regenerating vertexmesh array...
8269 // check if any dynamic vertex processing must occur
8270 dynamicvertex = false;
8272 // if there is a chance of animated vertex colors, it's a dynamic batch
8273 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8275 dynamicvertex = true;
8276 batchneed |= BATCHNEED_NOGAPS;
8277 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8280 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8282 switch (deform->deform)
8285 case Q3DEFORM_PROJECTIONSHADOW:
8286 case Q3DEFORM_TEXT0:
8287 case Q3DEFORM_TEXT1:
8288 case Q3DEFORM_TEXT2:
8289 case Q3DEFORM_TEXT3:
8290 case Q3DEFORM_TEXT4:
8291 case Q3DEFORM_TEXT5:
8292 case Q3DEFORM_TEXT6:
8293 case Q3DEFORM_TEXT7:
8296 case Q3DEFORM_AUTOSPRITE:
8297 dynamicvertex = true;
8298 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8299 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8301 case Q3DEFORM_AUTOSPRITE2:
8302 dynamicvertex = true;
8303 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8304 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8306 case Q3DEFORM_NORMAL:
8307 dynamicvertex = true;
8308 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8309 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8312 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8313 break; // if wavefunc is a nop, ignore this transform
8314 dynamicvertex = true;
8315 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8316 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8318 case Q3DEFORM_BULGE:
8319 dynamicvertex = true;
8320 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8321 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8324 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8325 break; // if wavefunc is a nop, ignore this transform
8326 dynamicvertex = true;
8327 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8328 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8332 switch(rsurface.texture->tcgen.tcgen)
8335 case Q3TCGEN_TEXTURE:
8337 case Q3TCGEN_LIGHTMAP:
8338 dynamicvertex = true;
8339 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8340 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8342 case Q3TCGEN_VECTOR:
8343 dynamicvertex = true;
8344 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8345 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8347 case Q3TCGEN_ENVIRONMENT:
8348 dynamicvertex = true;
8349 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8350 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8353 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8355 dynamicvertex = true;
8356 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8357 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8360 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8362 dynamicvertex = true;
8363 batchneed |= BATCHNEED_NOGAPS;
8364 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8367 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8369 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8370 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8371 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8372 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8373 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8374 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8375 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8378 // when the model data has no vertex buffer (dynamic mesh), we need to
8380 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8381 batchneed |= BATCHNEED_NOGAPS;
8383 // if needsupdate, we have to do a dynamic vertex batch for sure
8384 if (needsupdate & batchneed)
8385 dynamicvertex = true;
8387 // see if we need to build vertexmesh from arrays
8388 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8389 dynamicvertex = true;
8391 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8392 // also some drivers strongly dislike firstvertex
8393 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8394 dynamicvertex = true;
8396 rsurface.batchvertex3f = rsurface.modelvertex3f;
8397 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8398 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8399 rsurface.batchsvector3f = rsurface.modelsvector3f;
8400 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8401 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8402 rsurface.batchtvector3f = rsurface.modeltvector3f;
8403 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8404 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8405 rsurface.batchnormal3f = rsurface.modelnormal3f;
8406 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8407 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8408 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8409 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8410 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8411 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8412 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8413 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8414 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8415 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8416 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8417 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8418 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8419 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8420 rsurface.batchelement3i = rsurface.modelelement3i;
8421 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8422 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8423 rsurface.batchelement3s = rsurface.modelelement3s;
8424 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8425 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8427 // if any dynamic vertex processing has to occur in software, we copy the
8428 // entire surface list together before processing to rebase the vertices
8429 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8431 // if any gaps exist and we do not have a static vertex buffer, we have to
8432 // copy the surface list together to avoid wasting upload bandwidth on the
8433 // vertices in the gaps.
8435 // if gaps exist and we have a static vertex buffer, we still have to
8436 // combine the index buffer ranges into one dynamic index buffer.
8438 // in all cases we end up with data that can be drawn in one call.
8442 // static vertex data, just set pointers...
8443 rsurface.batchgeneratedvertex = false;
8444 // if there are gaps, we want to build a combined index buffer,
8445 // otherwise use the original static buffer with an appropriate offset
8448 // build a new triangle elements array for this batch
8449 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8450 rsurface.batchfirsttriangle = 0;
8452 for (i = 0;i < texturenumsurfaces;i++)
8454 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8455 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8456 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8457 numtriangles += surfacenumtriangles;
8459 rsurface.batchelement3i_indexbuffer = NULL;
8460 rsurface.batchelement3i_bufferoffset = 0;
8461 rsurface.batchelement3s = NULL;
8462 rsurface.batchelement3s_indexbuffer = NULL;
8463 rsurface.batchelement3s_bufferoffset = 0;
8464 if (endvertex <= 65536)
8466 // make a 16bit (unsigned short) index array if possible
8467 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8468 for (i = 0;i < numtriangles*3;i++)
8469 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8475 // something needs software processing, do it for real...
8476 // we only directly handle separate array data in this case and then
8477 // generate interleaved data if needed...
8478 rsurface.batchgeneratedvertex = true;
8480 // now copy the vertex data into a combined array and make an index array
8481 // (this is what Quake3 does all the time)
8482 //if (gaps || rsurface.batchfirstvertex)
8484 rsurface.batchvertex3fbuffer = NULL;
8485 rsurface.batchvertexmesh = NULL;
8486 rsurface.batchvertexmeshbuffer = NULL;
8487 rsurface.batchvertex3f = NULL;
8488 rsurface.batchvertex3f_vertexbuffer = NULL;
8489 rsurface.batchvertex3f_bufferoffset = 0;
8490 rsurface.batchsvector3f = NULL;
8491 rsurface.batchsvector3f_vertexbuffer = NULL;
8492 rsurface.batchsvector3f_bufferoffset = 0;
8493 rsurface.batchtvector3f = NULL;
8494 rsurface.batchtvector3f_vertexbuffer = NULL;
8495 rsurface.batchtvector3f_bufferoffset = 0;
8496 rsurface.batchnormal3f = NULL;
8497 rsurface.batchnormal3f_vertexbuffer = NULL;
8498 rsurface.batchnormal3f_bufferoffset = 0;
8499 rsurface.batchlightmapcolor4f = NULL;
8500 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8501 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8502 rsurface.batchtexcoordtexture2f = NULL;
8503 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8504 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8505 rsurface.batchtexcoordlightmap2f = NULL;
8506 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8507 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8508 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8509 rsurface.batchelement3i_indexbuffer = NULL;
8510 rsurface.batchelement3i_bufferoffset = 0;
8511 rsurface.batchelement3s = NULL;
8512 rsurface.batchelement3s_indexbuffer = NULL;
8513 rsurface.batchelement3s_bufferoffset = 0;
8514 // we'll only be setting up certain arrays as needed
8515 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8516 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8517 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8518 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8519 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8520 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8521 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8523 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8524 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8526 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8527 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8528 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8529 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8530 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8531 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8534 for (i = 0;i < texturenumsurfaces;i++)
8536 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8537 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8538 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8539 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8540 // copy only the data requested
8541 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8542 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8543 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8545 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8546 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8547 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8548 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8549 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8551 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8552 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8554 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8555 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8556 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8557 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8558 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8559 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8561 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8562 numvertices += surfacenumvertices;
8563 numtriangles += surfacenumtriangles;
8566 // generate a 16bit index array as well if possible
8567 // (in general, dynamic batches fit)
8568 if (numvertices <= 65536)
8570 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8571 for (i = 0;i < numtriangles*3;i++)
8572 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8575 // since we've copied everything, the batch now starts at 0
8576 rsurface.batchfirstvertex = 0;
8577 rsurface.batchnumvertices = batchnumvertices;
8578 rsurface.batchfirsttriangle = 0;
8579 rsurface.batchnumtriangles = batchnumtriangles;
8582 // q1bsp surfaces rendered in vertex color mode have to have colors
8583 // calculated based on lightstyles
8584 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8586 // generate color arrays for the surfaces in this list
8591 const unsigned char *lm;
8592 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8593 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8594 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8596 for (i = 0;i < texturenumsurfaces;i++)
8598 surface = texturesurfacelist[i];
8599 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8600 surfacenumvertices = surface->num_vertices;
8601 if (surface->lightmapinfo->samples)
8603 for (j = 0;j < surfacenumvertices;j++)
8605 lm = surface->lightmapinfo->samples + offsets[j];
8606 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8607 VectorScale(lm, scale, c);
8608 if (surface->lightmapinfo->styles[1] != 255)
8610 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8612 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8613 VectorMA(c, scale, lm, c);
8614 if (surface->lightmapinfo->styles[2] != 255)
8617 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8618 VectorMA(c, scale, lm, c);
8619 if (surface->lightmapinfo->styles[3] != 255)
8622 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8623 VectorMA(c, scale, lm, c);
8630 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);
8636 for (j = 0;j < surfacenumvertices;j++)
8638 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8645 // if vertices are deformed (sprite flares and things in maps, possibly
8646 // water waves, bulges and other deformations), modify the copied vertices
8648 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8650 switch (deform->deform)
8653 case Q3DEFORM_PROJECTIONSHADOW:
8654 case Q3DEFORM_TEXT0:
8655 case Q3DEFORM_TEXT1:
8656 case Q3DEFORM_TEXT2:
8657 case Q3DEFORM_TEXT3:
8658 case Q3DEFORM_TEXT4:
8659 case Q3DEFORM_TEXT5:
8660 case Q3DEFORM_TEXT6:
8661 case Q3DEFORM_TEXT7:
8664 case Q3DEFORM_AUTOSPRITE:
8665 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8666 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8667 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8668 VectorNormalize(newforward);
8669 VectorNormalize(newright);
8670 VectorNormalize(newup);
8671 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8672 // rsurface.batchvertex3f_vertexbuffer = NULL;
8673 // rsurface.batchvertex3f_bufferoffset = 0;
8674 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8675 // rsurface.batchsvector3f_vertexbuffer = NULL;
8676 // rsurface.batchsvector3f_bufferoffset = 0;
8677 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8678 // rsurface.batchtvector3f_vertexbuffer = NULL;
8679 // rsurface.batchtvector3f_bufferoffset = 0;
8680 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8681 // rsurface.batchnormal3f_vertexbuffer = NULL;
8682 // rsurface.batchnormal3f_bufferoffset = 0;
8683 // a single autosprite surface can contain multiple sprites...
8684 for (j = 0;j < batchnumvertices - 3;j += 4)
8686 VectorClear(center);
8687 for (i = 0;i < 4;i++)
8688 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8689 VectorScale(center, 0.25f, center);
8690 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8691 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8692 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8693 for (i = 0;i < 4;i++)
8695 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8696 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8699 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8700 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8701 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);
8703 case Q3DEFORM_AUTOSPRITE2:
8704 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8705 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8706 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8707 VectorNormalize(newforward);
8708 VectorNormalize(newright);
8709 VectorNormalize(newup);
8710 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8711 // rsurface.batchvertex3f_vertexbuffer = NULL;
8712 // rsurface.batchvertex3f_bufferoffset = 0;
8714 const float *v1, *v2;
8724 memset(shortest, 0, sizeof(shortest));
8725 // a single autosprite surface can contain multiple sprites...
8726 for (j = 0;j < batchnumvertices - 3;j += 4)
8728 VectorClear(center);
8729 for (i = 0;i < 4;i++)
8730 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8731 VectorScale(center, 0.25f, center);
8732 // find the two shortest edges, then use them to define the
8733 // axis vectors for rotating around the central axis
8734 for (i = 0;i < 6;i++)
8736 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8737 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8738 l = VectorDistance2(v1, v2);
8739 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8741 l += (1.0f / 1024.0f);
8742 if (shortest[0].length2 > l || i == 0)
8744 shortest[1] = shortest[0];
8745 shortest[0].length2 = l;
8746 shortest[0].v1 = v1;
8747 shortest[0].v2 = v2;
8749 else if (shortest[1].length2 > l || i == 1)
8751 shortest[1].length2 = l;
8752 shortest[1].v1 = v1;
8753 shortest[1].v2 = v2;
8756 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8757 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8758 // this calculates the right vector from the shortest edge
8759 // and the up vector from the edge midpoints
8760 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8761 VectorNormalize(right);
8762 VectorSubtract(end, start, up);
8763 VectorNormalize(up);
8764 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8765 VectorSubtract(rsurface.localvieworigin, center, forward);
8766 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8767 VectorNegate(forward, forward);
8768 VectorReflect(forward, 0, up, forward);
8769 VectorNormalize(forward);
8770 CrossProduct(up, forward, newright);
8771 VectorNormalize(newright);
8772 // rotate the quad around the up axis vector, this is made
8773 // especially easy by the fact we know the quad is flat,
8774 // so we only have to subtract the center position and
8775 // measure distance along the right vector, and then
8776 // multiply that by the newright vector and add back the
8778 // we also need to subtract the old position to undo the
8779 // displacement from the center, which we do with a
8780 // DotProduct, the subtraction/addition of center is also
8781 // optimized into DotProducts here
8782 l = DotProduct(right, center);
8783 for (i = 0;i < 4;i++)
8785 v1 = rsurface.batchvertex3f + 3*(j+i);
8786 f = DotProduct(right, v1) - l;
8787 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8791 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8793 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8794 // rsurface.batchnormal3f_vertexbuffer = NULL;
8795 // rsurface.batchnormal3f_bufferoffset = 0;
8796 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8798 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8800 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8801 // rsurface.batchsvector3f_vertexbuffer = NULL;
8802 // rsurface.batchsvector3f_bufferoffset = 0;
8803 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8804 // rsurface.batchtvector3f_vertexbuffer = NULL;
8805 // rsurface.batchtvector3f_bufferoffset = 0;
8806 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);
8809 case Q3DEFORM_NORMAL:
8810 // deform the normals to make reflections wavey
8811 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8812 rsurface.batchnormal3f_vertexbuffer = NULL;
8813 rsurface.batchnormal3f_bufferoffset = 0;
8814 for (j = 0;j < batchnumvertices;j++)
8817 float *normal = rsurface.batchnormal3f + 3*j;
8818 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8819 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8820 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]);
8821 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]);
8822 VectorNormalize(normal);
8824 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8826 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8827 // rsurface.batchsvector3f_vertexbuffer = NULL;
8828 // rsurface.batchsvector3f_bufferoffset = 0;
8829 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8830 // rsurface.batchtvector3f_vertexbuffer = NULL;
8831 // rsurface.batchtvector3f_bufferoffset = 0;
8832 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);
8836 // deform vertex array to make wavey water and flags and such
8837 waveparms[0] = deform->waveparms[0];
8838 waveparms[1] = deform->waveparms[1];
8839 waveparms[2] = deform->waveparms[2];
8840 waveparms[3] = deform->waveparms[3];
8841 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8842 break; // if wavefunc is a nop, don't make a dynamic vertex array
8843 // this is how a divisor of vertex influence on deformation
8844 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8845 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8846 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8847 // rsurface.batchvertex3f_vertexbuffer = NULL;
8848 // rsurface.batchvertex3f_bufferoffset = 0;
8849 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8850 // rsurface.batchnormal3f_vertexbuffer = NULL;
8851 // rsurface.batchnormal3f_bufferoffset = 0;
8852 for (j = 0;j < batchnumvertices;j++)
8854 // if the wavefunc depends on time, evaluate it per-vertex
8857 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8858 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8860 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8862 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8863 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8864 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8866 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8867 // rsurface.batchsvector3f_vertexbuffer = NULL;
8868 // rsurface.batchsvector3f_bufferoffset = 0;
8869 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8870 // rsurface.batchtvector3f_vertexbuffer = NULL;
8871 // rsurface.batchtvector3f_bufferoffset = 0;
8872 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);
8875 case Q3DEFORM_BULGE:
8876 // deform vertex array to make the surface have moving bulges
8877 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8878 // rsurface.batchvertex3f_vertexbuffer = NULL;
8879 // rsurface.batchvertex3f_bufferoffset = 0;
8880 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8881 // rsurface.batchnormal3f_vertexbuffer = NULL;
8882 // rsurface.batchnormal3f_bufferoffset = 0;
8883 for (j = 0;j < batchnumvertices;j++)
8885 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8886 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8888 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8889 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8890 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8892 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8893 // rsurface.batchsvector3f_vertexbuffer = NULL;
8894 // rsurface.batchsvector3f_bufferoffset = 0;
8895 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8896 // rsurface.batchtvector3f_vertexbuffer = NULL;
8897 // rsurface.batchtvector3f_bufferoffset = 0;
8898 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);
8902 // deform vertex array
8903 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8904 break; // if wavefunc is a nop, don't make a dynamic vertex array
8905 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8906 VectorScale(deform->parms, scale, waveparms);
8907 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8908 // rsurface.batchvertex3f_vertexbuffer = NULL;
8909 // rsurface.batchvertex3f_bufferoffset = 0;
8910 for (j = 0;j < batchnumvertices;j++)
8911 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8916 // generate texcoords based on the chosen texcoord source
8917 switch(rsurface.texture->tcgen.tcgen)
8920 case Q3TCGEN_TEXTURE:
8922 case Q3TCGEN_LIGHTMAP:
8923 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8924 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8925 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8926 if (rsurface.batchtexcoordlightmap2f)
8927 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8929 case Q3TCGEN_VECTOR:
8930 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8931 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8932 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8933 for (j = 0;j < batchnumvertices;j++)
8935 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8936 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8939 case Q3TCGEN_ENVIRONMENT:
8940 // make environment reflections using a spheremap
8941 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8942 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8943 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8944 for (j = 0;j < batchnumvertices;j++)
8946 // identical to Q3A's method, but executed in worldspace so
8947 // carried models can be shiny too
8949 float viewer[3], d, reflected[3], worldreflected[3];
8951 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8952 // VectorNormalize(viewer);
8954 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8956 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8957 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8958 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8959 // note: this is proportinal to viewer, so we can normalize later
8961 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8962 VectorNormalize(worldreflected);
8964 // note: this sphere map only uses world x and z!
8965 // so positive and negative y will LOOK THE SAME.
8966 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8967 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8971 // the only tcmod that needs software vertex processing is turbulent, so
8972 // check for it here and apply the changes if needed
8973 // and we only support that as the first one
8974 // (handling a mixture of turbulent and other tcmods would be problematic
8975 // without punting it entirely to a software path)
8976 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8978 amplitude = rsurface.texture->tcmods[0].parms[1];
8979 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8980 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8981 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8982 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8983 for (j = 0;j < batchnumvertices;j++)
8985 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);
8986 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8990 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8992 // convert the modified arrays to vertex structs
8993 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8994 // rsurface.batchvertexmeshbuffer = NULL;
8995 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8996 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8997 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8998 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8999 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9000 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9001 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9003 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9005 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9006 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9009 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9010 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9011 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9012 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9013 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9014 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9015 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9016 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9017 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9021 void RSurf_DrawBatch(void)
9023 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9024 // through the pipeline, killing it earlier in the pipeline would have
9025 // per-surface overhead rather than per-batch overhead, so it's best to
9026 // reject it here, before it hits glDraw.
9027 if (rsurface.batchnumtriangles == 0)
9030 // batch debugging code
9031 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9037 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9038 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9041 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9043 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9045 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9046 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);
9053 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);
9056 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9058 // pick the closest matching water plane
9059 int planeindex, vertexindex, bestplaneindex = -1;
9063 r_waterstate_waterplane_t *p;
9064 qboolean prepared = false;
9066 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9068 if(p->camera_entity != rsurface.texture->camera_entity)
9073 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9075 if(rsurface.batchnumvertices == 0)
9078 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9080 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9081 d += fabs(PlaneDiff(vert, &p->plane));
9083 if (bestd > d || bestplaneindex < 0)
9086 bestplaneindex = planeindex;
9089 return bestplaneindex;
9090 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9091 // this situation though, as it might be better to render single larger
9092 // batches with useless stuff (backface culled for example) than to
9093 // render multiple smaller batches
9096 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9099 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9100 rsurface.passcolor4f_vertexbuffer = 0;
9101 rsurface.passcolor4f_bufferoffset = 0;
9102 for (i = 0;i < rsurface.batchnumvertices;i++)
9103 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9106 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9113 if (rsurface.passcolor4f)
9115 // generate color arrays
9116 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9117 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9118 rsurface.passcolor4f_vertexbuffer = 0;
9119 rsurface.passcolor4f_bufferoffset = 0;
9120 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)
9122 f = RSurf_FogVertex(v);
9131 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9132 rsurface.passcolor4f_vertexbuffer = 0;
9133 rsurface.passcolor4f_bufferoffset = 0;
9134 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9136 f = RSurf_FogVertex(v);
9145 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9152 if (!rsurface.passcolor4f)
9154 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9155 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9156 rsurface.passcolor4f_vertexbuffer = 0;
9157 rsurface.passcolor4f_bufferoffset = 0;
9158 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)
9160 f = RSurf_FogVertex(v);
9161 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9162 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9163 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9168 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9173 if (!rsurface.passcolor4f)
9175 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9176 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9177 rsurface.passcolor4f_vertexbuffer = 0;
9178 rsurface.passcolor4f_bufferoffset = 0;
9179 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9188 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9193 if (!rsurface.passcolor4f)
9195 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9196 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9197 rsurface.passcolor4f_vertexbuffer = 0;
9198 rsurface.passcolor4f_bufferoffset = 0;
9199 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9201 c2[0] = c[0] + r_refdef.scene.ambient;
9202 c2[1] = c[1] + r_refdef.scene.ambient;
9203 c2[2] = c[2] + r_refdef.scene.ambient;
9208 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9211 rsurface.passcolor4f = NULL;
9212 rsurface.passcolor4f_vertexbuffer = 0;
9213 rsurface.passcolor4f_bufferoffset = 0;
9214 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9215 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9216 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9217 GL_Color(r, g, b, a);
9218 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9222 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9224 // TODO: optimize applyfog && applycolor case
9225 // just apply fog if necessary, and tint the fog color array if necessary
9226 rsurface.passcolor4f = NULL;
9227 rsurface.passcolor4f_vertexbuffer = 0;
9228 rsurface.passcolor4f_bufferoffset = 0;
9229 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9230 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9231 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9232 GL_Color(r, g, b, a);
9236 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9239 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9240 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9241 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9242 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9243 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9244 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9245 GL_Color(r, g, b, a);
9249 static void RSurf_DrawBatch_GL11_ClampColor(void)
9254 if (!rsurface.passcolor4f)
9256 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9258 c2[0] = bound(0.0f, c1[0], 1.0f);
9259 c2[1] = bound(0.0f, c1[1], 1.0f);
9260 c2[2] = bound(0.0f, c1[2], 1.0f);
9261 c2[3] = bound(0.0f, c1[3], 1.0f);
9265 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9275 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9276 rsurface.passcolor4f_vertexbuffer = 0;
9277 rsurface.passcolor4f_bufferoffset = 0;
9278 for (i = 0, 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)
9280 f = -DotProduct(r_refdef.view.forward, n);
9282 f = f * 0.85 + 0.15; // work around so stuff won't get black
9283 f *= r_refdef.lightmapintensity;
9284 Vector4Set(c, f, f, f, 1);
9288 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9290 RSurf_DrawBatch_GL11_ApplyFakeLight();
9291 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9292 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9293 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9294 GL_Color(r, g, b, a);
9298 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9306 vec3_t ambientcolor;
9307 vec3_t diffusecolor;
9311 VectorCopy(rsurface.modellight_lightdir, lightdir);
9312 f = 0.5f * r_refdef.lightmapintensity;
9313 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9314 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9315 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9316 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9317 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9318 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9320 if (VectorLength2(diffusecolor) > 0)
9322 // q3-style directional shading
9323 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9324 rsurface.passcolor4f_vertexbuffer = 0;
9325 rsurface.passcolor4f_bufferoffset = 0;
9326 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)
9328 if ((f = DotProduct(n, lightdir)) > 0)
9329 VectorMA(ambientcolor, f, diffusecolor, c);
9331 VectorCopy(ambientcolor, c);
9338 *applycolor = false;
9342 *r = ambientcolor[0];
9343 *g = ambientcolor[1];
9344 *b = ambientcolor[2];
9345 rsurface.passcolor4f = NULL;
9346 rsurface.passcolor4f_vertexbuffer = 0;
9347 rsurface.passcolor4f_bufferoffset = 0;
9351 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9353 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9354 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9355 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9356 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9357 GL_Color(r, g, b, a);
9361 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9369 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9370 rsurface.passcolor4f_vertexbuffer = 0;
9371 rsurface.passcolor4f_bufferoffset = 0;
9373 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9375 f = 1 - RSurf_FogVertex(v);
9383 void RSurf_SetupDepthAndCulling(void)
9385 // submodels are biased to avoid z-fighting with world surfaces that they
9386 // may be exactly overlapping (avoids z-fighting artifacts on certain
9387 // doors and things in Quake maps)
9388 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9389 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9390 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9391 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9394 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9396 // transparent sky would be ridiculous
9397 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9399 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9400 skyrenderlater = true;
9401 RSurf_SetupDepthAndCulling();
9403 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9404 // skymasking on them, and Quake3 never did sky masking (unlike
9405 // software Quake and software Quake2), so disable the sky masking
9406 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9407 // and skymasking also looks very bad when noclipping outside the
9408 // level, so don't use it then either.
9409 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9411 R_Mesh_ResetTextureState();
9412 if (skyrendermasked)
9414 R_SetupShader_DepthOrShadow();
9415 // depth-only (masking)
9416 GL_ColorMask(0,0,0,0);
9417 // just to make sure that braindead drivers don't draw
9418 // anything despite that colormask...
9419 GL_BlendFunc(GL_ZERO, GL_ONE);
9420 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9421 if (rsurface.batchvertex3fbuffer)
9422 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9424 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9428 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9430 GL_BlendFunc(GL_ONE, GL_ZERO);
9431 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9432 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9433 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9436 if (skyrendermasked)
9437 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9439 R_Mesh_ResetTextureState();
9440 GL_Color(1, 1, 1, 1);
9443 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9444 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9445 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9447 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9451 // render screenspace normalmap to texture
9453 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9458 // bind lightmap texture
9460 // water/refraction/reflection/camera surfaces have to be handled specially
9461 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9463 int start, end, startplaneindex;
9464 for (start = 0;start < texturenumsurfaces;start = end)
9466 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9467 if(startplaneindex < 0)
9469 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9470 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9474 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9476 // now that we have a batch using the same planeindex, render it
9477 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9479 // render water or distortion background
9481 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));
9483 // blend surface on top
9484 GL_DepthMask(false);
9485 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9488 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9490 // render surface with reflection texture as input
9491 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9492 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));
9499 // render surface batch normally
9500 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9501 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9505 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9507 // OpenGL 1.3 path - anything not completely ancient
9508 qboolean applycolor;
9511 const texturelayer_t *layer;
9512 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);
9513 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9515 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9518 int layertexrgbscale;
9519 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9521 if (layerindex == 0)
9525 GL_AlphaTest(false);
9526 GL_DepthFunc(GL_EQUAL);
9529 GL_DepthMask(layer->depthmask && writedepth);
9530 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9531 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9533 layertexrgbscale = 4;
9534 VectorScale(layer->color, 0.25f, layercolor);
9536 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9538 layertexrgbscale = 2;
9539 VectorScale(layer->color, 0.5f, layercolor);
9543 layertexrgbscale = 1;
9544 VectorScale(layer->color, 1.0f, layercolor);
9546 layercolor[3] = layer->color[3];
9547 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9548 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9549 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9550 switch (layer->type)
9552 case TEXTURELAYERTYPE_LITTEXTURE:
9553 // single-pass lightmapped texture with 2x rgbscale
9554 R_Mesh_TexBind(0, r_texture_white);
9555 R_Mesh_TexMatrix(0, NULL);
9556 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9557 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9558 R_Mesh_TexBind(1, layer->texture);
9559 R_Mesh_TexMatrix(1, &layer->texmatrix);
9560 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9561 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9562 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9563 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9564 else if (FAKELIGHT_ENABLED)
9565 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9566 else if (rsurface.uselightmaptexture)
9567 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9569 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9571 case TEXTURELAYERTYPE_TEXTURE:
9572 // singletexture unlit texture with transparency support
9573 R_Mesh_TexBind(0, layer->texture);
9574 R_Mesh_TexMatrix(0, &layer->texmatrix);
9575 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9576 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9577 R_Mesh_TexBind(1, 0);
9578 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9579 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9581 case TEXTURELAYERTYPE_FOG:
9582 // singletexture fogging
9585 R_Mesh_TexBind(0, layer->texture);
9586 R_Mesh_TexMatrix(0, &layer->texmatrix);
9587 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9588 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9592 R_Mesh_TexBind(0, 0);
9593 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9595 R_Mesh_TexBind(1, 0);
9596 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9597 // generate a color array for the fog pass
9598 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9599 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9603 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9606 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9608 GL_DepthFunc(GL_LEQUAL);
9609 GL_AlphaTest(false);
9613 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9615 // OpenGL 1.1 - crusty old voodoo path
9618 const texturelayer_t *layer;
9619 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);
9620 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9622 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9624 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9626 if (layerindex == 0)
9630 GL_AlphaTest(false);
9631 GL_DepthFunc(GL_EQUAL);
9634 GL_DepthMask(layer->depthmask && writedepth);
9635 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9636 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9637 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9638 switch (layer->type)
9640 case TEXTURELAYERTYPE_LITTEXTURE:
9641 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9643 // two-pass lit texture with 2x rgbscale
9644 // first the lightmap pass
9645 R_Mesh_TexBind(0, r_texture_white);
9646 R_Mesh_TexMatrix(0, NULL);
9647 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9648 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9649 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9650 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9651 else if (FAKELIGHT_ENABLED)
9652 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9653 else if (rsurface.uselightmaptexture)
9654 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9656 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9657 // then apply the texture to it
9658 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9659 R_Mesh_TexBind(0, layer->texture);
9660 R_Mesh_TexMatrix(0, &layer->texmatrix);
9661 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9662 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9663 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);
9667 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9668 R_Mesh_TexBind(0, layer->texture);
9669 R_Mesh_TexMatrix(0, &layer->texmatrix);
9670 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9671 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9672 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9673 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);
9675 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);
9678 case TEXTURELAYERTYPE_TEXTURE:
9679 // singletexture unlit texture with transparency support
9680 R_Mesh_TexBind(0, layer->texture);
9681 R_Mesh_TexMatrix(0, &layer->texmatrix);
9682 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9683 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9684 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);
9686 case TEXTURELAYERTYPE_FOG:
9687 // singletexture fogging
9690 R_Mesh_TexBind(0, layer->texture);
9691 R_Mesh_TexMatrix(0, &layer->texmatrix);
9692 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9693 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9697 R_Mesh_TexBind(0, 0);
9698 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9700 // generate a color array for the fog pass
9701 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9702 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9706 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9709 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9711 GL_DepthFunc(GL_LEQUAL);
9712 GL_AlphaTest(false);
9716 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9720 r_vertexgeneric_t *batchvertex;
9723 // R_Mesh_ResetTextureState();
9724 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9726 if(rsurface.texture && rsurface.texture->currentskinframe)
9728 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9729 c[3] *= rsurface.texture->currentalpha;
9739 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9741 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9742 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9743 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9746 // brighten it up (as texture value 127 means "unlit")
9747 c[0] *= 2 * r_refdef.view.colorscale;
9748 c[1] *= 2 * r_refdef.view.colorscale;
9749 c[2] *= 2 * r_refdef.view.colorscale;
9751 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9752 c[3] *= r_wateralpha.value;
9754 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9756 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9757 GL_DepthMask(false);
9759 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9761 GL_BlendFunc(GL_ONE, GL_ONE);
9762 GL_DepthMask(false);
9764 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9766 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9767 GL_DepthMask(false);
9769 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9771 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9772 GL_DepthMask(false);
9776 GL_BlendFunc(GL_ONE, GL_ZERO);
9777 GL_DepthMask(writedepth);
9780 if (r_showsurfaces.integer == 3)
9782 rsurface.passcolor4f = NULL;
9784 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9786 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9788 rsurface.passcolor4f = NULL;
9789 rsurface.passcolor4f_vertexbuffer = 0;
9790 rsurface.passcolor4f_bufferoffset = 0;
9792 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9794 qboolean applycolor = true;
9797 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9799 r_refdef.lightmapintensity = 1;
9800 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9801 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9803 else if (FAKELIGHT_ENABLED)
9805 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9807 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9808 RSurf_DrawBatch_GL11_ApplyFakeLight();
9809 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9813 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9815 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9816 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9817 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9820 if(!rsurface.passcolor4f)
9821 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9823 RSurf_DrawBatch_GL11_ApplyAmbient();
9824 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9825 if(r_refdef.fogenabled)
9826 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9827 RSurf_DrawBatch_GL11_ClampColor();
9829 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9830 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9833 else if (!r_refdef.view.showdebug)
9835 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9836 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9837 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9839 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9840 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9842 R_Mesh_PrepareVertices_Generic_Unlock();
9845 else if (r_showsurfaces.integer == 4)
9847 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9848 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9849 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9851 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9852 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9853 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9855 R_Mesh_PrepareVertices_Generic_Unlock();
9858 else if (r_showsurfaces.integer == 2)
9861 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9862 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9863 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9865 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9866 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9867 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9868 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9869 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9870 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9871 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9873 R_Mesh_PrepareVertices_Generic_Unlock();
9874 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9878 int texturesurfaceindex;
9880 const msurface_t *surface;
9881 float surfacecolor4f[4];
9882 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9883 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9885 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9887 surface = texturesurfacelist[texturesurfaceindex];
9888 k = (int)(((size_t)surface) / sizeof(msurface_t));
9889 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9890 for (j = 0;j < surface->num_vertices;j++)
9892 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9893 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9897 R_Mesh_PrepareVertices_Generic_Unlock();
9902 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9905 RSurf_SetupDepthAndCulling();
9906 if (r_showsurfaces.integer)
9908 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9911 switch (vid.renderpath)
9913 case RENDERPATH_GL20:
9914 case RENDERPATH_D3D9:
9915 case RENDERPATH_D3D10:
9916 case RENDERPATH_D3D11:
9917 case RENDERPATH_SOFT:
9918 case RENDERPATH_GLES2:
9919 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9921 case RENDERPATH_GL13:
9922 case RENDERPATH_GLES1:
9923 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9925 case RENDERPATH_GL11:
9926 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9932 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9935 RSurf_SetupDepthAndCulling();
9936 if (r_showsurfaces.integer)
9938 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9941 switch (vid.renderpath)
9943 case RENDERPATH_GL20:
9944 case RENDERPATH_D3D9:
9945 case RENDERPATH_D3D10:
9946 case RENDERPATH_D3D11:
9947 case RENDERPATH_SOFT:
9948 case RENDERPATH_GLES2:
9949 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9951 case RENDERPATH_GL13:
9952 case RENDERPATH_GLES1:
9953 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9955 case RENDERPATH_GL11:
9956 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9962 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9965 int texturenumsurfaces, endsurface;
9967 const msurface_t *surface;
9968 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9970 // if the model is static it doesn't matter what value we give for
9971 // wantnormals and wanttangents, so this logic uses only rules applicable
9972 // to a model, knowing that they are meaningless otherwise
9973 if (ent == r_refdef.scene.worldentity)
9974 RSurf_ActiveWorldEntity();
9975 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9976 RSurf_ActiveModelEntity(ent, false, false, false);
9979 switch (vid.renderpath)
9981 case RENDERPATH_GL20:
9982 case RENDERPATH_D3D9:
9983 case RENDERPATH_D3D10:
9984 case RENDERPATH_D3D11:
9985 case RENDERPATH_SOFT:
9986 case RENDERPATH_GLES2:
9987 RSurf_ActiveModelEntity(ent, true, true, false);
9989 case RENDERPATH_GL11:
9990 case RENDERPATH_GL13:
9991 case RENDERPATH_GLES1:
9992 RSurf_ActiveModelEntity(ent, true, false, false);
9997 if (r_transparentdepthmasking.integer)
9999 qboolean setup = false;
10000 for (i = 0;i < numsurfaces;i = j)
10003 surface = rsurface.modelsurfaces + surfacelist[i];
10004 texture = surface->texture;
10005 rsurface.texture = R_GetCurrentTexture(texture);
10006 rsurface.lightmaptexture = NULL;
10007 rsurface.deluxemaptexture = NULL;
10008 rsurface.uselightmaptexture = false;
10009 // scan ahead until we find a different texture
10010 endsurface = min(i + 1024, numsurfaces);
10011 texturenumsurfaces = 0;
10012 texturesurfacelist[texturenumsurfaces++] = surface;
10013 for (;j < endsurface;j++)
10015 surface = rsurface.modelsurfaces + surfacelist[j];
10016 if (texture != surface->texture)
10018 texturesurfacelist[texturenumsurfaces++] = surface;
10020 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10022 // render the range of surfaces as depth
10026 GL_ColorMask(0,0,0,0);
10028 GL_DepthTest(true);
10029 GL_BlendFunc(GL_ONE, GL_ZERO);
10030 GL_DepthMask(true);
10031 // R_Mesh_ResetTextureState();
10032 R_SetupShader_DepthOrShadow();
10034 RSurf_SetupDepthAndCulling();
10035 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10036 if (rsurface.batchvertex3fbuffer)
10037 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10039 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10043 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10046 for (i = 0;i < numsurfaces;i = j)
10049 surface = rsurface.modelsurfaces + surfacelist[i];
10050 texture = surface->texture;
10051 rsurface.texture = R_GetCurrentTexture(texture);
10052 // scan ahead until we find a different texture
10053 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10054 texturenumsurfaces = 0;
10055 texturesurfacelist[texturenumsurfaces++] = surface;
10056 if(FAKELIGHT_ENABLED)
10058 rsurface.lightmaptexture = NULL;
10059 rsurface.deluxemaptexture = NULL;
10060 rsurface.uselightmaptexture = false;
10061 for (;j < endsurface;j++)
10063 surface = rsurface.modelsurfaces + surfacelist[j];
10064 if (texture != surface->texture)
10066 texturesurfacelist[texturenumsurfaces++] = surface;
10071 rsurface.lightmaptexture = surface->lightmaptexture;
10072 rsurface.deluxemaptexture = surface->deluxemaptexture;
10073 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10074 for (;j < endsurface;j++)
10076 surface = rsurface.modelsurfaces + surfacelist[j];
10077 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10079 texturesurfacelist[texturenumsurfaces++] = surface;
10082 // render the range of surfaces
10083 if (ent == r_refdef.scene.worldentity)
10084 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10086 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10088 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10091 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10093 // transparent surfaces get pushed off into the transparent queue
10094 int surfacelistindex;
10095 const msurface_t *surface;
10096 vec3_t tempcenter, center;
10097 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10099 surface = texturesurfacelist[surfacelistindex];
10100 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10101 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10102 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10103 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10104 if (queueentity->transparent_offset) // transparent offset
10106 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10107 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10108 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10110 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10114 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10116 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10118 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10120 RSurf_SetupDepthAndCulling();
10121 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10122 if (rsurface.batchvertex3fbuffer)
10123 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10125 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10129 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10131 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10134 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10137 if (!rsurface.texture->currentnumlayers)
10139 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10140 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10142 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10144 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10145 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10146 else if (!rsurface.texture->currentnumlayers)
10148 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10150 // in the deferred case, transparent surfaces were queued during prepass
10151 if (!r_shadow_usingdeferredprepass)
10152 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10156 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10157 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10162 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10165 texture_t *texture;
10166 R_FrameData_SetMark();
10167 // break the surface list down into batches by texture and use of lightmapping
10168 for (i = 0;i < numsurfaces;i = j)
10171 // texture is the base texture pointer, rsurface.texture is the
10172 // current frame/skin the texture is directing us to use (for example
10173 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10174 // use skin 1 instead)
10175 texture = surfacelist[i]->texture;
10176 rsurface.texture = R_GetCurrentTexture(texture);
10177 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10179 // if this texture is not the kind we want, skip ahead to the next one
10180 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10184 if(FAKELIGHT_ENABLED || depthonly || prepass)
10186 rsurface.lightmaptexture = NULL;
10187 rsurface.deluxemaptexture = NULL;
10188 rsurface.uselightmaptexture = false;
10189 // simply scan ahead until we find a different texture or lightmap state
10190 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10195 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10196 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10197 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10198 // simply scan ahead until we find a different texture or lightmap state
10199 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10202 // render the range of surfaces
10203 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10205 R_FrameData_ReturnToMark();
10208 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10212 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10215 if (!rsurface.texture->currentnumlayers)
10217 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10218 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10220 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10222 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10223 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10224 else if (!rsurface.texture->currentnumlayers)
10226 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10228 // in the deferred case, transparent surfaces were queued during prepass
10229 if (!r_shadow_usingdeferredprepass)
10230 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10234 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10235 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10240 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10243 texture_t *texture;
10244 R_FrameData_SetMark();
10245 // break the surface list down into batches by texture and use of lightmapping
10246 for (i = 0;i < numsurfaces;i = j)
10249 // texture is the base texture pointer, rsurface.texture is the
10250 // current frame/skin the texture is directing us to use (for example
10251 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10252 // use skin 1 instead)
10253 texture = surfacelist[i]->texture;
10254 rsurface.texture = R_GetCurrentTexture(texture);
10255 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10257 // if this texture is not the kind we want, skip ahead to the next one
10258 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10262 if(FAKELIGHT_ENABLED || depthonly || prepass)
10264 rsurface.lightmaptexture = NULL;
10265 rsurface.deluxemaptexture = NULL;
10266 rsurface.uselightmaptexture = false;
10267 // simply scan ahead until we find a different texture or lightmap state
10268 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10273 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10274 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10275 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10276 // simply scan ahead until we find a different texture or lightmap state
10277 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10280 // render the range of surfaces
10281 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10283 R_FrameData_ReturnToMark();
10286 float locboxvertex3f[6*4*3] =
10288 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10289 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10290 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10291 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10292 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10293 1,0,0, 0,0,0, 0,1,0, 1,1,0
10296 unsigned short locboxelements[6*2*3] =
10301 12,13,14, 12,14,15,
10302 16,17,18, 16,18,19,
10306 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10309 cl_locnode_t *loc = (cl_locnode_t *)ent;
10311 float vertex3f[6*4*3];
10313 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10314 GL_DepthMask(false);
10315 GL_DepthRange(0, 1);
10316 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10317 GL_DepthTest(true);
10318 GL_CullFace(GL_NONE);
10319 R_EntityMatrix(&identitymatrix);
10321 // R_Mesh_ResetTextureState();
10323 i = surfacelist[0];
10324 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10325 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10326 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10327 surfacelist[0] < 0 ? 0.5f : 0.125f);
10329 if (VectorCompare(loc->mins, loc->maxs))
10331 VectorSet(size, 2, 2, 2);
10332 VectorMA(loc->mins, -0.5f, size, mins);
10336 VectorCopy(loc->mins, mins);
10337 VectorSubtract(loc->maxs, loc->mins, size);
10340 for (i = 0;i < 6*4*3;)
10341 for (j = 0;j < 3;j++, i++)
10342 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10344 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10345 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10346 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10349 void R_DrawLocs(void)
10352 cl_locnode_t *loc, *nearestloc;
10354 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10355 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10357 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10358 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10362 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10364 if (decalsystem->decals)
10365 Mem_Free(decalsystem->decals);
10366 memset(decalsystem, 0, sizeof(*decalsystem));
10369 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)
10372 tridecal_t *decals;
10375 // expand or initialize the system
10376 if (decalsystem->maxdecals <= decalsystem->numdecals)
10378 decalsystem_t old = *decalsystem;
10379 qboolean useshortelements;
10380 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10381 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10382 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)));
10383 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10384 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10385 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10386 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10387 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10388 if (decalsystem->numdecals)
10389 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10391 Mem_Free(old.decals);
10392 for (i = 0;i < decalsystem->maxdecals*3;i++)
10393 decalsystem->element3i[i] = i;
10394 if (useshortelements)
10395 for (i = 0;i < decalsystem->maxdecals*3;i++)
10396 decalsystem->element3s[i] = i;
10399 // grab a decal and search for another free slot for the next one
10400 decals = decalsystem->decals;
10401 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10402 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10404 decalsystem->freedecal = i;
10405 if (decalsystem->numdecals <= i)
10406 decalsystem->numdecals = i + 1;
10408 // initialize the decal
10410 decal->triangleindex = triangleindex;
10411 decal->surfaceindex = surfaceindex;
10412 decal->decalsequence = decalsequence;
10413 decal->color4f[0][0] = c0[0];
10414 decal->color4f[0][1] = c0[1];
10415 decal->color4f[0][2] = c0[2];
10416 decal->color4f[0][3] = 1;
10417 decal->color4f[1][0] = c1[0];
10418 decal->color4f[1][1] = c1[1];
10419 decal->color4f[1][2] = c1[2];
10420 decal->color4f[1][3] = 1;
10421 decal->color4f[2][0] = c2[0];
10422 decal->color4f[2][1] = c2[1];
10423 decal->color4f[2][2] = c2[2];
10424 decal->color4f[2][3] = 1;
10425 decal->vertex3f[0][0] = v0[0];
10426 decal->vertex3f[0][1] = v0[1];
10427 decal->vertex3f[0][2] = v0[2];
10428 decal->vertex3f[1][0] = v1[0];
10429 decal->vertex3f[1][1] = v1[1];
10430 decal->vertex3f[1][2] = v1[2];
10431 decal->vertex3f[2][0] = v2[0];
10432 decal->vertex3f[2][1] = v2[1];
10433 decal->vertex3f[2][2] = v2[2];
10434 decal->texcoord2f[0][0] = t0[0];
10435 decal->texcoord2f[0][1] = t0[1];
10436 decal->texcoord2f[1][0] = t1[0];
10437 decal->texcoord2f[1][1] = t1[1];
10438 decal->texcoord2f[2][0] = t2[0];
10439 decal->texcoord2f[2][1] = t2[1];
10440 TriangleNormal(v0, v1, v2, decal->plane);
10441 VectorNormalize(decal->plane);
10442 decal->plane[3] = DotProduct(v0, decal->plane);
10445 extern cvar_t cl_decals_bias;
10446 extern cvar_t cl_decals_models;
10447 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10448 // baseparms, parms, temps
10449 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)
10454 const float *vertex3f;
10455 const float *normal3f;
10457 float points[2][9][3];
10464 e = rsurface.modelelement3i + 3*triangleindex;
10466 vertex3f = rsurface.modelvertex3f;
10467 normal3f = rsurface.modelnormal3f;
10471 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10473 index = 3*e[cornerindex];
10474 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10479 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10481 index = 3*e[cornerindex];
10482 VectorCopy(vertex3f + index, v[cornerindex]);
10487 //TriangleNormal(v[0], v[1], v[2], normal);
10488 //if (DotProduct(normal, localnormal) < 0.0f)
10490 // clip by each of the box planes formed from the projection matrix
10491 // if anything survives, we emit the decal
10492 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]);
10495 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]);
10498 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]);
10501 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]);
10504 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]);
10507 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]);
10510 // some part of the triangle survived, so we have to accept it...
10513 // dynamic always uses the original triangle
10515 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10517 index = 3*e[cornerindex];
10518 VectorCopy(vertex3f + index, v[cornerindex]);
10521 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10523 // convert vertex positions to texcoords
10524 Matrix4x4_Transform(projection, v[cornerindex], temp);
10525 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10526 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10527 // calculate distance fade from the projection origin
10528 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10529 f = bound(0.0f, f, 1.0f);
10530 c[cornerindex][0] = r * f;
10531 c[cornerindex][1] = g * f;
10532 c[cornerindex][2] = b * f;
10533 c[cornerindex][3] = 1.0f;
10534 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10537 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);
10539 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10540 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);
10542 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)
10544 matrix4x4_t projection;
10545 decalsystem_t *decalsystem;
10548 const msurface_t *surface;
10549 const msurface_t *surfaces;
10550 const int *surfacelist;
10551 const texture_t *texture;
10553 int numsurfacelist;
10554 int surfacelistindex;
10557 float localorigin[3];
10558 float localnormal[3];
10559 float localmins[3];
10560 float localmaxs[3];
10563 float planes[6][4];
10566 int bih_triangles_count;
10567 int bih_triangles[256];
10568 int bih_surfaces[256];
10570 decalsystem = &ent->decalsystem;
10571 model = ent->model;
10572 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10574 R_DecalSystem_Reset(&ent->decalsystem);
10578 if (!model->brush.data_leafs && !cl_decals_models.integer)
10580 if (decalsystem->model)
10581 R_DecalSystem_Reset(decalsystem);
10585 if (decalsystem->model != model)
10586 R_DecalSystem_Reset(decalsystem);
10587 decalsystem->model = model;
10589 RSurf_ActiveModelEntity(ent, true, false, false);
10591 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10592 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10593 VectorNormalize(localnormal);
10594 localsize = worldsize*rsurface.inversematrixscale;
10595 localmins[0] = localorigin[0] - localsize;
10596 localmins[1] = localorigin[1] - localsize;
10597 localmins[2] = localorigin[2] - localsize;
10598 localmaxs[0] = localorigin[0] + localsize;
10599 localmaxs[1] = localorigin[1] + localsize;
10600 localmaxs[2] = localorigin[2] + localsize;
10602 //VectorCopy(localnormal, planes[4]);
10603 //VectorVectors(planes[4], planes[2], planes[0]);
10604 AnglesFromVectors(angles, localnormal, NULL, false);
10605 AngleVectors(angles, planes[0], planes[2], planes[4]);
10606 VectorNegate(planes[0], planes[1]);
10607 VectorNegate(planes[2], planes[3]);
10608 VectorNegate(planes[4], planes[5]);
10609 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10610 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10611 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10612 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10613 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10614 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10619 matrix4x4_t forwardprojection;
10620 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10621 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10626 float projectionvector[4][3];
10627 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10628 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10629 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10630 projectionvector[0][0] = planes[0][0] * ilocalsize;
10631 projectionvector[0][1] = planes[1][0] * ilocalsize;
10632 projectionvector[0][2] = planes[2][0] * ilocalsize;
10633 projectionvector[1][0] = planes[0][1] * ilocalsize;
10634 projectionvector[1][1] = planes[1][1] * ilocalsize;
10635 projectionvector[1][2] = planes[2][1] * ilocalsize;
10636 projectionvector[2][0] = planes[0][2] * ilocalsize;
10637 projectionvector[2][1] = planes[1][2] * ilocalsize;
10638 projectionvector[2][2] = planes[2][2] * ilocalsize;
10639 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10640 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10641 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10642 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10646 dynamic = model->surfmesh.isanimated;
10647 numsurfacelist = model->nummodelsurfaces;
10648 surfacelist = model->sortedmodelsurfaces;
10649 surfaces = model->data_surfaces;
10652 bih_triangles_count = -1;
10655 if(model->render_bih.numleafs)
10656 bih = &model->render_bih;
10657 else if(model->collision_bih.numleafs)
10658 bih = &model->collision_bih;
10661 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10662 if(bih_triangles_count == 0)
10664 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10666 if(bih_triangles_count > 0)
10668 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10670 surfaceindex = bih_surfaces[triangleindex];
10671 surface = surfaces + surfaceindex;
10672 texture = surface->texture;
10673 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10675 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10677 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10682 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10684 surfaceindex = surfacelist[surfacelistindex];
10685 surface = surfaces + surfaceindex;
10686 // check cull box first because it rejects more than any other check
10687 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10689 // skip transparent surfaces
10690 texture = surface->texture;
10691 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10693 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10695 numtriangles = surface->num_triangles;
10696 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10697 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10702 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10703 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)
10705 int renderentityindex;
10706 float worldmins[3];
10707 float worldmaxs[3];
10708 entity_render_t *ent;
10710 if (!cl_decals_newsystem.integer)
10713 worldmins[0] = worldorigin[0] - worldsize;
10714 worldmins[1] = worldorigin[1] - worldsize;
10715 worldmins[2] = worldorigin[2] - worldsize;
10716 worldmaxs[0] = worldorigin[0] + worldsize;
10717 worldmaxs[1] = worldorigin[1] + worldsize;
10718 worldmaxs[2] = worldorigin[2] + worldsize;
10720 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10722 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10724 ent = r_refdef.scene.entities[renderentityindex];
10725 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10728 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10732 typedef struct r_decalsystem_splatqueue_s
10734 vec3_t worldorigin;
10735 vec3_t worldnormal;
10741 r_decalsystem_splatqueue_t;
10743 int r_decalsystem_numqueued = 0;
10744 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10746 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)
10748 r_decalsystem_splatqueue_t *queue;
10750 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10753 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10754 VectorCopy(worldorigin, queue->worldorigin);
10755 VectorCopy(worldnormal, queue->worldnormal);
10756 Vector4Set(queue->color, r, g, b, a);
10757 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10758 queue->worldsize = worldsize;
10759 queue->decalsequence = cl.decalsequence++;
10762 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10765 r_decalsystem_splatqueue_t *queue;
10767 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10768 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);
10769 r_decalsystem_numqueued = 0;
10772 extern cvar_t cl_decals_max;
10773 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10776 decalsystem_t *decalsystem = &ent->decalsystem;
10783 if (!decalsystem->numdecals)
10786 if (r_showsurfaces.integer)
10789 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10791 R_DecalSystem_Reset(decalsystem);
10795 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10796 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10798 if (decalsystem->lastupdatetime)
10799 frametime = (cl.time - decalsystem->lastupdatetime);
10802 decalsystem->lastupdatetime = cl.time;
10803 decal = decalsystem->decals;
10804 numdecals = decalsystem->numdecals;
10806 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10808 if (decal->color4f[0][3])
10810 decal->lived += frametime;
10811 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10813 memset(decal, 0, sizeof(*decal));
10814 if (decalsystem->freedecal > i)
10815 decalsystem->freedecal = i;
10819 decal = decalsystem->decals;
10820 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10823 // collapse the array by shuffling the tail decals into the gaps
10826 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10827 decalsystem->freedecal++;
10828 if (decalsystem->freedecal == numdecals)
10830 decal[decalsystem->freedecal] = decal[--numdecals];
10833 decalsystem->numdecals = numdecals;
10835 if (numdecals <= 0)
10837 // if there are no decals left, reset decalsystem
10838 R_DecalSystem_Reset(decalsystem);
10842 extern skinframe_t *decalskinframe;
10843 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10846 decalsystem_t *decalsystem = &ent->decalsystem;
10855 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10858 numdecals = decalsystem->numdecals;
10862 if (r_showsurfaces.integer)
10865 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10867 R_DecalSystem_Reset(decalsystem);
10871 // if the model is static it doesn't matter what value we give for
10872 // wantnormals and wanttangents, so this logic uses only rules applicable
10873 // to a model, knowing that they are meaningless otherwise
10874 if (ent == r_refdef.scene.worldentity)
10875 RSurf_ActiveWorldEntity();
10877 RSurf_ActiveModelEntity(ent, false, false, false);
10879 decalsystem->lastupdatetime = cl.time;
10880 decal = decalsystem->decals;
10882 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10884 // update vertex positions for animated models
10885 v3f = decalsystem->vertex3f;
10886 c4f = decalsystem->color4f;
10887 t2f = decalsystem->texcoord2f;
10888 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10890 if (!decal->color4f[0][3])
10893 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10897 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10900 // update color values for fading decals
10901 if (decal->lived >= cl_decals_time.value)
10902 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10906 c4f[ 0] = decal->color4f[0][0] * alpha;
10907 c4f[ 1] = decal->color4f[0][1] * alpha;
10908 c4f[ 2] = decal->color4f[0][2] * alpha;
10910 c4f[ 4] = decal->color4f[1][0] * alpha;
10911 c4f[ 5] = decal->color4f[1][1] * alpha;
10912 c4f[ 6] = decal->color4f[1][2] * alpha;
10914 c4f[ 8] = decal->color4f[2][0] * alpha;
10915 c4f[ 9] = decal->color4f[2][1] * alpha;
10916 c4f[10] = decal->color4f[2][2] * alpha;
10919 t2f[0] = decal->texcoord2f[0][0];
10920 t2f[1] = decal->texcoord2f[0][1];
10921 t2f[2] = decal->texcoord2f[1][0];
10922 t2f[3] = decal->texcoord2f[1][1];
10923 t2f[4] = decal->texcoord2f[2][0];
10924 t2f[5] = decal->texcoord2f[2][1];
10926 // update vertex positions for animated models
10927 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10929 e = rsurface.modelelement3i + 3*decal->triangleindex;
10930 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10931 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10932 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10936 VectorCopy(decal->vertex3f[0], v3f);
10937 VectorCopy(decal->vertex3f[1], v3f + 3);
10938 VectorCopy(decal->vertex3f[2], v3f + 6);
10941 if (r_refdef.fogenabled)
10943 alpha = RSurf_FogVertex(v3f);
10944 VectorScale(c4f, alpha, c4f);
10945 alpha = RSurf_FogVertex(v3f + 3);
10946 VectorScale(c4f + 4, alpha, c4f + 4);
10947 alpha = RSurf_FogVertex(v3f + 6);
10948 VectorScale(c4f + 8, alpha, c4f + 8);
10959 r_refdef.stats.drawndecals += numtris;
10961 // now render the decals all at once
10962 // (this assumes they all use one particle font texture!)
10963 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);
10964 // R_Mesh_ResetTextureState();
10965 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10966 GL_DepthMask(false);
10967 GL_DepthRange(0, 1);
10968 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10969 GL_DepthTest(true);
10970 GL_CullFace(GL_NONE);
10971 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10972 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10973 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10977 static void R_DrawModelDecals(void)
10981 // fade faster when there are too many decals
10982 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10983 for (i = 0;i < r_refdef.scene.numentities;i++)
10984 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10986 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10987 for (i = 0;i < r_refdef.scene.numentities;i++)
10988 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10989 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10991 R_DecalSystem_ApplySplatEntitiesQueue();
10993 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10994 for (i = 0;i < r_refdef.scene.numentities;i++)
10995 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10997 r_refdef.stats.totaldecals += numdecals;
10999 if (r_showsurfaces.integer)
11002 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11004 for (i = 0;i < r_refdef.scene.numentities;i++)
11006 if (!r_refdef.viewcache.entityvisible[i])
11008 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11009 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11013 extern cvar_t mod_collision_bih;
11014 void R_DrawDebugModel(void)
11016 entity_render_t *ent = rsurface.entity;
11017 int i, j, k, l, flagsmask;
11018 const msurface_t *surface;
11019 dp_model_t *model = ent->model;
11022 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11025 if (r_showoverdraw.value > 0)
11027 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11028 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11029 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11030 GL_DepthTest(false);
11031 GL_DepthMask(false);
11032 GL_DepthRange(0, 1);
11033 GL_BlendFunc(GL_ONE, GL_ONE);
11034 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11036 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11038 rsurface.texture = R_GetCurrentTexture(surface->texture);
11039 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11041 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11042 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11043 if (!rsurface.texture->currentlayers->depthmask)
11044 GL_Color(c, 0, 0, 1.0f);
11045 else if (ent == r_refdef.scene.worldentity)
11046 GL_Color(c, c, c, 1.0f);
11048 GL_Color(0, c, 0, 1.0f);
11049 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11053 rsurface.texture = NULL;
11056 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11058 // R_Mesh_ResetTextureState();
11059 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11060 GL_DepthRange(0, 1);
11061 GL_DepthTest(!r_showdisabledepthtest.integer);
11062 GL_DepthMask(false);
11063 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11065 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11069 qboolean cullbox = ent == r_refdef.scene.worldentity;
11070 const q3mbrush_t *brush;
11071 const bih_t *bih = &model->collision_bih;
11072 const bih_leaf_t *bihleaf;
11073 float vertex3f[3][3];
11074 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11076 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11078 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11080 switch (bihleaf->type)
11083 brush = model->brush.data_brushes + bihleaf->itemindex;
11084 if (brush->colbrushf && brush->colbrushf->numtriangles)
11086 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);
11087 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11088 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11091 case BIH_COLLISIONTRIANGLE:
11092 triangleindex = bihleaf->itemindex;
11093 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11094 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11095 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11096 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);
11097 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11098 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11100 case BIH_RENDERTRIANGLE:
11101 triangleindex = bihleaf->itemindex;
11102 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11103 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11104 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11105 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11106 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11107 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11113 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11115 if (r_showtris.integer && qglPolygonMode)
11117 if (r_showdisabledepthtest.integer)
11119 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11120 GL_DepthMask(false);
11124 GL_BlendFunc(GL_ONE, GL_ZERO);
11125 GL_DepthMask(true);
11127 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11128 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11130 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11132 rsurface.texture = R_GetCurrentTexture(surface->texture);
11133 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11135 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11136 if (!rsurface.texture->currentlayers->depthmask)
11137 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11138 else if (ent == r_refdef.scene.worldentity)
11139 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11141 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11142 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11146 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11147 rsurface.texture = NULL;
11150 if (r_shownormals.value != 0 && qglBegin)
11152 if (r_showdisabledepthtest.integer)
11154 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11155 GL_DepthMask(false);
11159 GL_BlendFunc(GL_ONE, GL_ZERO);
11160 GL_DepthMask(true);
11162 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11164 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11166 rsurface.texture = R_GetCurrentTexture(surface->texture);
11167 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11169 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11170 qglBegin(GL_LINES);
11171 if (r_shownormals.value < 0)
11173 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11175 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11176 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11177 qglVertex3f(v[0], v[1], v[2]);
11178 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11179 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11180 qglVertex3f(v[0], v[1], v[2]);
11183 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11185 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11187 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11188 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11189 qglVertex3f(v[0], v[1], v[2]);
11190 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11191 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11192 qglVertex3f(v[0], v[1], v[2]);
11194 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11196 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11197 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11198 qglVertex3f(v[0], v[1], v[2]);
11199 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11200 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11201 qglVertex3f(v[0], v[1], v[2]);
11203 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11205 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11206 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11207 qglVertex3f(v[0], v[1], v[2]);
11208 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11209 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11210 qglVertex3f(v[0], v[1], v[2]);
11217 rsurface.texture = NULL;
11221 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11222 int r_maxsurfacelist = 0;
11223 const msurface_t **r_surfacelist = NULL;
11224 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11226 int i, j, endj, flagsmask;
11227 dp_model_t *model = r_refdef.scene.worldmodel;
11228 msurface_t *surfaces;
11229 unsigned char *update;
11230 int numsurfacelist = 0;
11234 if (r_maxsurfacelist < model->num_surfaces)
11236 r_maxsurfacelist = model->num_surfaces;
11238 Mem_Free((msurface_t**)r_surfacelist);
11239 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11242 RSurf_ActiveWorldEntity();
11244 surfaces = model->data_surfaces;
11245 update = model->brushq1.lightmapupdateflags;
11247 // update light styles on this submodel
11248 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11250 model_brush_lightstyleinfo_t *style;
11251 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11253 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11255 int *list = style->surfacelist;
11256 style->value = r_refdef.scene.lightstylevalue[style->style];
11257 for (j = 0;j < style->numsurfaces;j++)
11258 update[list[j]] = true;
11263 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11267 R_DrawDebugModel();
11268 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11272 rsurface.lightmaptexture = NULL;
11273 rsurface.deluxemaptexture = NULL;
11274 rsurface.uselightmaptexture = false;
11275 rsurface.texture = NULL;
11276 rsurface.rtlight = NULL;
11277 numsurfacelist = 0;
11278 // add visible surfaces to draw list
11279 for (i = 0;i < model->nummodelsurfaces;i++)
11281 j = model->sortedmodelsurfaces[i];
11282 if (r_refdef.viewcache.world_surfacevisible[j])
11283 r_surfacelist[numsurfacelist++] = surfaces + j;
11285 // update lightmaps if needed
11286 if (model->brushq1.firstrender)
11288 model->brushq1.firstrender = false;
11289 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11291 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11295 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11296 if (r_refdef.viewcache.world_surfacevisible[j])
11298 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11300 // don't do anything if there were no surfaces
11301 if (!numsurfacelist)
11303 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11306 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11308 // add to stats if desired
11309 if (r_speeds.integer && !skysurfaces && !depthonly)
11311 r_refdef.stats.world_surfaces += numsurfacelist;
11312 for (j = 0;j < numsurfacelist;j++)
11313 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11316 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11319 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11321 int i, j, endj, flagsmask;
11322 dp_model_t *model = ent->model;
11323 msurface_t *surfaces;
11324 unsigned char *update;
11325 int numsurfacelist = 0;
11329 if (r_maxsurfacelist < model->num_surfaces)
11331 r_maxsurfacelist = model->num_surfaces;
11333 Mem_Free((msurface_t **)r_surfacelist);
11334 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11337 // if the model is static it doesn't matter what value we give for
11338 // wantnormals and wanttangents, so this logic uses only rules applicable
11339 // to a model, knowing that they are meaningless otherwise
11340 if (ent == r_refdef.scene.worldentity)
11341 RSurf_ActiveWorldEntity();
11342 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11343 RSurf_ActiveModelEntity(ent, false, false, false);
11345 RSurf_ActiveModelEntity(ent, true, true, true);
11346 else if (depthonly)
11348 switch (vid.renderpath)
11350 case RENDERPATH_GL20:
11351 case RENDERPATH_D3D9:
11352 case RENDERPATH_D3D10:
11353 case RENDERPATH_D3D11:
11354 case RENDERPATH_SOFT:
11355 case RENDERPATH_GLES2:
11356 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11358 case RENDERPATH_GL11:
11359 case RENDERPATH_GL13:
11360 case RENDERPATH_GLES1:
11361 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11367 switch (vid.renderpath)
11369 case RENDERPATH_GL20:
11370 case RENDERPATH_D3D9:
11371 case RENDERPATH_D3D10:
11372 case RENDERPATH_D3D11:
11373 case RENDERPATH_SOFT:
11374 case RENDERPATH_GLES2:
11375 RSurf_ActiveModelEntity(ent, true, true, false);
11377 case RENDERPATH_GL11:
11378 case RENDERPATH_GL13:
11379 case RENDERPATH_GLES1:
11380 RSurf_ActiveModelEntity(ent, true, false, false);
11385 surfaces = model->data_surfaces;
11386 update = model->brushq1.lightmapupdateflags;
11388 // update light styles
11389 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11391 model_brush_lightstyleinfo_t *style;
11392 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11394 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11396 int *list = style->surfacelist;
11397 style->value = r_refdef.scene.lightstylevalue[style->style];
11398 for (j = 0;j < style->numsurfaces;j++)
11399 update[list[j]] = true;
11404 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11408 R_DrawDebugModel();
11409 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11413 rsurface.lightmaptexture = NULL;
11414 rsurface.deluxemaptexture = NULL;
11415 rsurface.uselightmaptexture = false;
11416 rsurface.texture = NULL;
11417 rsurface.rtlight = NULL;
11418 numsurfacelist = 0;
11419 // add visible surfaces to draw list
11420 for (i = 0;i < model->nummodelsurfaces;i++)
11421 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11422 // don't do anything if there were no surfaces
11423 if (!numsurfacelist)
11425 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11428 // update lightmaps if needed
11432 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11437 R_BuildLightMap(ent, surfaces + j);
11442 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11444 R_BuildLightMap(ent, surfaces + j);
11445 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11447 // add to stats if desired
11448 if (r_speeds.integer && !skysurfaces && !depthonly)
11450 r_refdef.stats.entities_surfaces += numsurfacelist;
11451 for (j = 0;j < numsurfacelist;j++)
11452 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11455 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11458 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11460 static texture_t texture;
11461 static msurface_t surface;
11462 const msurface_t *surfacelist = &surface;
11464 // fake enough texture and surface state to render this geometry
11466 texture.update_lastrenderframe = -1; // regenerate this texture
11467 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11468 texture.currentskinframe = skinframe;
11469 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11470 texture.offsetmapping = OFFSETMAPPING_OFF;
11471 texture.offsetscale = 1;
11472 texture.specularscalemod = 1;
11473 texture.specularpowermod = 1;
11475 surface.texture = &texture;
11476 surface.num_triangles = numtriangles;
11477 surface.num_firsttriangle = firsttriangle;
11478 surface.num_vertices = numvertices;
11479 surface.num_firstvertex = firstvertex;
11482 rsurface.texture = R_GetCurrentTexture(surface.texture);
11483 rsurface.lightmaptexture = NULL;
11484 rsurface.deluxemaptexture = NULL;
11485 rsurface.uselightmaptexture = false;
11486 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11489 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)
11491 static msurface_t surface;
11492 const msurface_t *surfacelist = &surface;
11494 // fake enough texture and surface state to render this geometry
11495 surface.texture = texture;
11496 surface.num_triangles = numtriangles;
11497 surface.num_firsttriangle = firsttriangle;
11498 surface.num_vertices = numvertices;
11499 surface.num_firstvertex = firstvertex;
11502 rsurface.texture = R_GetCurrentTexture(surface.texture);
11503 rsurface.lightmaptexture = NULL;
11504 rsurface.deluxemaptexture = NULL;
11505 rsurface.uselightmaptexture = false;
11506 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);