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 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5369 // calculate desired texture sizes
5370 // can't use water if the card does not support the texture size
5371 if (!r_water.integer || r_showsurfaces.integer)
5372 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5373 else if (vid.support.arb_texture_non_power_of_two)
5375 texturewidth = waterwidth;
5376 textureheight = waterheight;
5377 camerawidth = waterwidth;
5378 cameraheight = waterheight;
5382 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5383 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5384 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5385 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5388 // allocate textures as needed
5389 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5391 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5392 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5394 if (p->texture_refraction)
5395 R_FreeTexture(p->texture_refraction);
5396 p->texture_refraction = NULL;
5397 if (p->texture_reflection)
5398 R_FreeTexture(p->texture_reflection);
5399 p->texture_reflection = NULL;
5400 if (p->texture_camera)
5401 R_FreeTexture(p->texture_camera);
5402 p->texture_camera = NULL;
5404 memset(&r_waterstate, 0, sizeof(r_waterstate));
5405 r_waterstate.texturewidth = texturewidth;
5406 r_waterstate.textureheight = textureheight;
5407 r_waterstate.camerawidth = camerawidth;
5408 r_waterstate.cameraheight = cameraheight;
5411 if (r_waterstate.texturewidth)
5413 int scaledwidth, scaledheight;
5415 r_waterstate.enabled = true;
5417 // when doing a reduced render (HDR) we want to use a smaller area
5418 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5419 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5420 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5422 // set up variables that will be used in shader setup
5423 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5424 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5425 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5426 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5429 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5430 r_waterstate.numwaterplanes = 0;
5433 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5435 int triangleindex, planeindex;
5441 r_waterstate_waterplane_t *p;
5442 texture_t *t = R_GetCurrentTexture(surface->texture);
5444 // just use the first triangle with a valid normal for any decisions
5445 VectorClear(normal);
5446 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5448 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5449 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5450 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5451 TriangleNormal(vert[0], vert[1], vert[2], normal);
5452 if (VectorLength2(normal) >= 0.001)
5456 VectorCopy(normal, plane.normal);
5457 VectorNormalize(plane.normal);
5458 plane.dist = DotProduct(vert[0], plane.normal);
5459 PlaneClassify(&plane);
5460 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5462 // skip backfaces (except if nocullface is set)
5463 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5465 VectorNegate(plane.normal, plane.normal);
5467 PlaneClassify(&plane);
5471 // find a matching plane if there is one
5472 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5473 if(p->camera_entity == t->camera_entity)
5474 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5476 if (planeindex >= r_waterstate.maxwaterplanes)
5477 return; // nothing we can do, out of planes
5479 // if this triangle does not fit any known plane rendered this frame, add one
5480 if (planeindex >= r_waterstate.numwaterplanes)
5482 // store the new plane
5483 r_waterstate.numwaterplanes++;
5485 // clear materialflags and pvs
5486 p->materialflags = 0;
5487 p->pvsvalid = false;
5488 p->camera_entity = t->camera_entity;
5489 VectorCopy(surface->mins, p->mins);
5490 VectorCopy(surface->maxs, p->maxs);
5495 p->mins[0] = min(p->mins[0], surface->mins[0]);
5496 p->mins[1] = min(p->mins[1], surface->mins[1]);
5497 p->mins[2] = min(p->mins[2], surface->mins[2]);
5498 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5499 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5500 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5502 // merge this surface's materialflags into the waterplane
5503 p->materialflags |= t->currentmaterialflags;
5504 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5506 // merge this surface's PVS into the waterplane
5507 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5508 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5509 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5511 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5517 static void R_Water_ProcessPlanes(void)
5520 r_refdef_view_t originalview;
5521 r_refdef_view_t myview;
5523 r_waterstate_waterplane_t *p;
5526 originalview = r_refdef.view;
5528 // make sure enough textures are allocated
5529 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5531 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5533 if (!p->texture_refraction)
5534 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);
5535 if (!p->texture_refraction)
5538 else if (p->materialflags & MATERIALFLAG_CAMERA)
5540 if (!p->texture_camera)
5541 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);
5542 if (!p->texture_camera)
5546 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5548 if (!p->texture_reflection)
5549 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);
5550 if (!p->texture_reflection)
5556 r_refdef.view = originalview;
5557 r_refdef.view.showdebug = false;
5558 r_refdef.view.width = r_waterstate.waterwidth;
5559 r_refdef.view.height = r_waterstate.waterheight;
5560 r_refdef.view.useclipplane = true;
5561 myview = r_refdef.view;
5562 r_waterstate.renderingscene = true;
5563 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5565 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5567 r_refdef.view = myview;
5568 if(r_water_scissormode.integer)
5571 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5572 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5575 // render reflected scene and copy into texture
5576 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5577 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5578 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5579 r_refdef.view.clipplane = p->plane;
5581 // reverse the cullface settings for this render
5582 r_refdef.view.cullface_front = GL_FRONT;
5583 r_refdef.view.cullface_back = GL_BACK;
5584 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5586 r_refdef.view.usecustompvs = true;
5588 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5590 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5593 R_ResetViewRendering3D();
5594 R_ClearScreen(r_refdef.fogenabled);
5595 if(r_water_scissormode.integer & 2)
5596 R_View_UpdateWithScissor(myscissor);
5599 if(r_water_scissormode.integer & 1)
5600 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5603 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);
5606 // render the normal view scene and copy into texture
5607 // (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)
5608 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5610 r_refdef.view = myview;
5611 if(r_water_scissormode.integer)
5614 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5615 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5618 r_waterstate.renderingrefraction = true;
5620 r_refdef.view.clipplane = p->plane;
5621 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5622 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5624 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5626 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5627 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5628 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5629 R_RenderView_UpdateViewVectors();
5630 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5632 r_refdef.view.usecustompvs = true;
5633 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);
5637 PlaneClassify(&r_refdef.view.clipplane);
5639 R_ResetViewRendering3D();
5640 R_ClearScreen(r_refdef.fogenabled);
5641 if(r_water_scissormode.integer & 2)
5642 R_View_UpdateWithScissor(myscissor);
5645 if(r_water_scissormode.integer & 1)
5646 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5649 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);
5650 r_waterstate.renderingrefraction = false;
5652 else if (p->materialflags & MATERIALFLAG_CAMERA)
5654 r_refdef.view = myview;
5656 r_refdef.view.clipplane = p->plane;
5657 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5658 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5660 r_refdef.view.width = r_waterstate.camerawidth;
5661 r_refdef.view.height = r_waterstate.cameraheight;
5662 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5663 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5665 if(p->camera_entity)
5667 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5668 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5671 // note: all of the view is used for displaying... so
5672 // there is no use in scissoring
5674 // reverse the cullface settings for this render
5675 r_refdef.view.cullface_front = GL_FRONT;
5676 r_refdef.view.cullface_back = GL_BACK;
5677 // also reverse the view matrix
5678 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
5679 R_RenderView_UpdateViewVectors();
5680 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5682 r_refdef.view.usecustompvs = true;
5683 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);
5686 // camera needs no clipplane
5687 r_refdef.view.useclipplane = false;
5689 PlaneClassify(&r_refdef.view.clipplane);
5691 R_ResetViewRendering3D();
5692 R_ClearScreen(r_refdef.fogenabled);
5696 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);
5697 r_waterstate.renderingrefraction = false;
5701 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5702 r_waterstate.renderingscene = false;
5703 r_refdef.view = originalview;
5704 R_ResetViewRendering3D();
5705 R_ClearScreen(r_refdef.fogenabled);
5709 r_refdef.view = originalview;
5710 r_waterstate.renderingscene = false;
5711 Cvar_SetValueQuick(&r_water, 0);
5712 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5716 void R_Bloom_StartFrame(void)
5718 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5719 int viewwidth, viewheight;
5722 if (r_viewscale_fpsscaling.integer)
5724 double actualframetime;
5725 double targetframetime;
5727 actualframetime = r_refdef.lastdrawscreentime;
5728 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5729 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5730 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5731 if (r_viewscale_fpsscaling_stepsize.value > 0)
5732 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5733 viewscalefpsadjusted += adjust;
5734 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5737 viewscalefpsadjusted = 1.0f;
5739 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5741 switch(vid.renderpath)
5743 case RENDERPATH_GL20:
5744 case RENDERPATH_D3D9:
5745 case RENDERPATH_D3D10:
5746 case RENDERPATH_D3D11:
5747 case RENDERPATH_SOFT:
5748 case RENDERPATH_GLES2:
5750 case RENDERPATH_GL11:
5751 case RENDERPATH_GL13:
5752 case RENDERPATH_GLES1:
5756 // set bloomwidth and bloomheight to the bloom resolution that will be
5757 // used (often less than the screen resolution for faster rendering)
5758 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5759 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5760 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5761 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5762 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5764 // calculate desired texture sizes
5765 if (vid.support.arb_texture_non_power_of_two)
5767 screentexturewidth = vid.width;
5768 screentextureheight = vid.height;
5769 bloomtexturewidth = r_bloomstate.bloomwidth;
5770 bloomtextureheight = r_bloomstate.bloomheight;
5774 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5775 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5776 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5777 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5780 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))
5782 Cvar_SetValueQuick(&r_hdr, 0);
5783 Cvar_SetValueQuick(&r_bloom, 0);
5784 Cvar_SetValueQuick(&r_motionblur, 0);
5785 Cvar_SetValueQuick(&r_damageblur, 0);
5788 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)
5789 screentexturewidth = screentextureheight = 0;
5790 if (!r_hdr.integer && !r_bloom.integer)
5791 bloomtexturewidth = bloomtextureheight = 0;
5793 textype = TEXTYPE_COLORBUFFER;
5794 switch (vid.renderpath)
5796 case RENDERPATH_GL20:
5797 case RENDERPATH_GLES2:
5798 if (vid.support.ext_framebuffer_object)
5800 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5801 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5804 case RENDERPATH_GL11:
5805 case RENDERPATH_GL13:
5806 case RENDERPATH_GLES1:
5807 case RENDERPATH_D3D9:
5808 case RENDERPATH_D3D10:
5809 case RENDERPATH_D3D11:
5810 case RENDERPATH_SOFT:
5814 // allocate textures as needed
5815 if (r_bloomstate.screentexturewidth != screentexturewidth
5816 || r_bloomstate.screentextureheight != screentextureheight
5817 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5818 || r_bloomstate.bloomtextureheight != bloomtextureheight
5819 || r_bloomstate.texturetype != textype
5820 || r_bloomstate.viewfbo != r_viewfbo.integer)
5822 if (r_bloomstate.texture_bloom)
5823 R_FreeTexture(r_bloomstate.texture_bloom);
5824 r_bloomstate.texture_bloom = NULL;
5825 if (r_bloomstate.texture_screen)
5826 R_FreeTexture(r_bloomstate.texture_screen);
5827 r_bloomstate.texture_screen = NULL;
5828 if (r_bloomstate.fbo_framebuffer)
5829 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5830 r_bloomstate.fbo_framebuffer = 0;
5831 if (r_bloomstate.texture_framebuffercolor)
5832 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5833 r_bloomstate.texture_framebuffercolor = NULL;
5834 if (r_bloomstate.texture_framebufferdepth)
5835 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5836 r_bloomstate.texture_framebufferdepth = NULL;
5837 r_bloomstate.screentexturewidth = screentexturewidth;
5838 r_bloomstate.screentextureheight = screentextureheight;
5839 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5840 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);
5841 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5843 // FIXME: choose depth bits based on a cvar
5844 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5845 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);
5846 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5847 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5848 // render depth into one texture and normalmap into the other
5852 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5853 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5854 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5855 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5856 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5859 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5860 r_bloomstate.bloomtextureheight = bloomtextureheight;
5861 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5862 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);
5863 r_bloomstate.viewfbo = r_viewfbo.integer;
5864 r_bloomstate.texturetype = textype;
5867 // when doing a reduced render (HDR) we want to use a smaller area
5868 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5869 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5870 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5871 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5872 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5874 // set up a texcoord array for the full resolution screen image
5875 // (we have to keep this around to copy back during final render)
5876 r_bloomstate.screentexcoord2f[0] = 0;
5877 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5878 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5879 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5880 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5881 r_bloomstate.screentexcoord2f[5] = 0;
5882 r_bloomstate.screentexcoord2f[6] = 0;
5883 r_bloomstate.screentexcoord2f[7] = 0;
5885 // set up a texcoord array for the reduced resolution bloom image
5886 // (which will be additive blended over the screen image)
5887 r_bloomstate.bloomtexcoord2f[0] = 0;
5888 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5889 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5890 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5891 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5892 r_bloomstate.bloomtexcoord2f[5] = 0;
5893 r_bloomstate.bloomtexcoord2f[6] = 0;
5894 r_bloomstate.bloomtexcoord2f[7] = 0;
5896 switch(vid.renderpath)
5898 case RENDERPATH_GL11:
5899 case RENDERPATH_GL13:
5900 case RENDERPATH_GL20:
5901 case RENDERPATH_SOFT:
5902 case RENDERPATH_GLES1:
5903 case RENDERPATH_GLES2:
5905 case RENDERPATH_D3D9:
5906 case RENDERPATH_D3D10:
5907 case RENDERPATH_D3D11:
5910 for (i = 0;i < 4;i++)
5912 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5913 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5914 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5915 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5921 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5923 r_bloomstate.enabled = true;
5924 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5927 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);
5929 if (r_bloomstate.fbo_framebuffer)
5930 r_refdef.view.clear = true;
5933 void R_Bloom_CopyBloomTexture(float colorscale)
5935 r_refdef.stats.bloom++;
5937 // scale down screen texture to the bloom texture size
5939 R_Mesh_SetMainRenderTargets();
5940 R_SetViewport(&r_bloomstate.viewport);
5941 GL_BlendFunc(GL_ONE, GL_ZERO);
5942 GL_Color(colorscale, colorscale, colorscale, 1);
5943 // 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...
5944 switch(vid.renderpath)
5946 case RENDERPATH_GL11:
5947 case RENDERPATH_GL13:
5948 case RENDERPATH_GL20:
5949 case RENDERPATH_GLES1:
5950 case RENDERPATH_GLES2:
5951 case RENDERPATH_SOFT:
5952 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5954 case RENDERPATH_D3D9:
5955 case RENDERPATH_D3D10:
5956 case RENDERPATH_D3D11:
5957 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5960 // TODO: do boxfilter scale-down in shader?
5961 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5962 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5963 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5965 // we now have a bloom image in the framebuffer
5966 // copy it into the bloom image texture for later processing
5967 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);
5968 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5971 void R_Bloom_CopyHDRTexture(void)
5973 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);
5974 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5977 void R_Bloom_MakeTexture(void)
5980 float xoffset, yoffset, r, brighten;
5982 r_refdef.stats.bloom++;
5984 R_ResetViewRendering2D();
5986 // we have a bloom image in the framebuffer
5988 R_SetViewport(&r_bloomstate.viewport);
5990 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5993 r = bound(0, r_bloom_colorexponent.value / x, 1);
5994 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5996 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5997 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5998 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5999 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6001 // copy the vertically blurred bloom view to a texture
6002 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);
6003 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6006 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6007 brighten = r_bloom_brighten.value;
6008 if (r_bloomstate.hdr)
6009 brighten *= r_hdr_range.value;
6010 brighten = sqrt(brighten);
6012 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6013 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6015 for (dir = 0;dir < 2;dir++)
6017 // blend on at multiple vertical offsets to achieve a vertical blur
6018 // TODO: do offset blends using GLSL
6019 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6020 GL_BlendFunc(GL_ONE, GL_ZERO);
6021 for (x = -range;x <= range;x++)
6023 if (!dir){xoffset = 0;yoffset = x;}
6024 else {xoffset = x;yoffset = 0;}
6025 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6026 yoffset /= (float)r_bloomstate.bloomtextureheight;
6027 // compute a texcoord array with the specified x and y offset
6028 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6029 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6030 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6031 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6032 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6033 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6034 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6035 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6036 // this r value looks like a 'dot' particle, fading sharply to
6037 // black at the edges
6038 // (probably not realistic but looks good enough)
6039 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6040 //r = brighten/(range*2+1);
6041 r = brighten / (range * 2 + 1);
6043 r *= (1 - x*x/(float)(range*range));
6044 GL_Color(r, r, r, 1);
6045 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6046 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6047 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6048 GL_BlendFunc(GL_ONE, GL_ONE);
6051 // copy the vertically blurred bloom view to a texture
6052 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);
6053 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6057 void R_HDR_RenderBloomTexture(void)
6059 int oldwidth, oldheight;
6060 float oldcolorscale;
6061 qboolean oldwaterstate;
6063 oldwaterstate = r_waterstate.enabled;
6064 oldcolorscale = r_refdef.view.colorscale;
6065 oldwidth = r_refdef.view.width;
6066 oldheight = r_refdef.view.height;
6067 r_refdef.view.width = r_bloomstate.bloomwidth;
6068 r_refdef.view.height = r_bloomstate.bloomheight;
6070 if(r_hdr.integer < 2)
6071 r_waterstate.enabled = false;
6073 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6074 // TODO: add exposure compensation features
6075 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6077 r_refdef.view.showdebug = false;
6078 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6080 R_ResetViewRendering3D();
6082 R_ClearScreen(r_refdef.fogenabled);
6083 if (r_timereport_active)
6084 R_TimeReport("HDRclear");
6087 if (r_timereport_active)
6088 R_TimeReport("visibility");
6090 // only do secondary renders with HDR if r_hdr is 2 or higher
6091 r_waterstate.numwaterplanes = 0;
6092 if (r_waterstate.enabled)
6093 R_RenderWaterPlanes();
6095 r_refdef.view.showdebug = true;
6097 r_waterstate.numwaterplanes = 0;
6099 R_ResetViewRendering2D();
6101 R_Bloom_CopyHDRTexture();
6102 R_Bloom_MakeTexture();
6104 // restore the view settings
6105 r_waterstate.enabled = oldwaterstate;
6106 r_refdef.view.width = oldwidth;
6107 r_refdef.view.height = oldheight;
6108 r_refdef.view.colorscale = oldcolorscale;
6110 R_ResetViewRendering3D();
6112 R_ClearScreen(r_refdef.fogenabled);
6113 if (r_timereport_active)
6114 R_TimeReport("viewclear");
6117 static void R_BlendView(void)
6119 unsigned int permutation;
6120 float uservecs[4][4];
6122 switch (vid.renderpath)
6124 case RENDERPATH_GL20:
6125 case RENDERPATH_D3D9:
6126 case RENDERPATH_D3D10:
6127 case RENDERPATH_D3D11:
6128 case RENDERPATH_SOFT:
6129 case RENDERPATH_GLES2:
6131 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6132 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6133 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6134 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6135 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6137 if (r_bloomstate.texture_screen)
6139 // make sure the buffer is available
6140 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6142 R_ResetViewRendering2D();
6143 R_Mesh_SetMainRenderTargets();
6145 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6147 // declare variables
6149 static float avgspeed;
6151 speed = VectorLength(cl.movement_velocity);
6153 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6154 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6156 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6157 speed = bound(0, speed, 1);
6158 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6160 // calculate values into a standard alpha
6161 cl.motionbluralpha = 1 - exp(-
6163 (r_motionblur.value * speed / 80)
6165 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6168 max(0.0001, cl.time - cl.oldtime) // fps independent
6171 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6172 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6174 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6176 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6177 GL_Color(1, 1, 1, cl.motionbluralpha);
6178 switch(vid.renderpath)
6180 case RENDERPATH_GL11:
6181 case RENDERPATH_GL13:
6182 case RENDERPATH_GL20:
6183 case RENDERPATH_GLES1:
6184 case RENDERPATH_GLES2:
6185 case RENDERPATH_SOFT:
6186 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6188 case RENDERPATH_D3D9:
6189 case RENDERPATH_D3D10:
6190 case RENDERPATH_D3D11:
6191 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6194 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6195 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6196 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6200 // copy view into the screen texture
6201 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);
6202 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6204 else if (!r_bloomstate.texture_bloom)
6206 // we may still have to do view tint...
6207 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6209 // apply a color tint to the whole view
6210 R_ResetViewRendering2D();
6211 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6212 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6213 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6214 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6215 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6217 break; // no screen processing, no bloom, skip it
6220 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6222 // render simple bloom effect
6223 // copy the screen and shrink it and darken it for the bloom process
6224 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6225 // make the bloom texture
6226 R_Bloom_MakeTexture();
6229 #if _MSC_VER >= 1400
6230 #define sscanf sscanf_s
6232 memset(uservecs, 0, sizeof(uservecs));
6233 if (r_glsl_postprocess_uservec1_enable.integer)
6234 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6235 if (r_glsl_postprocess_uservec2_enable.integer)
6236 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6237 if (r_glsl_postprocess_uservec3_enable.integer)
6238 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6239 if (r_glsl_postprocess_uservec4_enable.integer)
6240 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6242 R_ResetViewRendering2D();
6243 GL_Color(1, 1, 1, 1);
6244 GL_BlendFunc(GL_ONE, GL_ZERO);
6246 switch(vid.renderpath)
6248 case RENDERPATH_GL20:
6249 case RENDERPATH_GLES2:
6250 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6251 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6252 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6253 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6254 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6255 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]);
6256 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6257 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]);
6258 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]);
6259 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]);
6260 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]);
6261 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6262 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6263 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);
6265 case RENDERPATH_D3D9:
6267 // 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...
6268 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6269 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6270 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6271 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6272 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6273 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6274 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6275 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6276 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6277 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6278 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6279 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6280 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6281 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6284 case RENDERPATH_D3D10:
6285 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6287 case RENDERPATH_D3D11:
6288 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6290 case RENDERPATH_SOFT:
6291 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6292 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6293 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6294 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6295 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6296 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6297 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6298 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6299 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6300 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6301 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6302 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6303 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6304 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6309 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6310 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6312 case RENDERPATH_GL11:
6313 case RENDERPATH_GL13:
6314 case RENDERPATH_GLES1:
6315 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6317 // apply a color tint to the whole view
6318 R_ResetViewRendering2D();
6319 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6320 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6321 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6322 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6323 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6329 matrix4x4_t r_waterscrollmatrix;
6331 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6333 if (r_refdef.fog_density)
6335 r_refdef.fogcolor[0] = r_refdef.fog_red;
6336 r_refdef.fogcolor[1] = r_refdef.fog_green;
6337 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6339 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6340 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6341 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6342 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6346 VectorCopy(r_refdef.fogcolor, fogvec);
6347 // color.rgb *= ContrastBoost * SceneBrightness;
6348 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6349 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6350 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6351 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6356 void R_UpdateVariables(void)
6360 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6362 r_refdef.farclip = r_farclip_base.value;
6363 if (r_refdef.scene.worldmodel)
6364 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6365 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6367 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6368 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6369 r_refdef.polygonfactor = 0;
6370 r_refdef.polygonoffset = 0;
6371 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6372 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6374 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6375 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6376 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6377 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6378 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6379 if (FAKELIGHT_ENABLED)
6381 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6383 if (r_showsurfaces.integer)
6385 r_refdef.scene.rtworld = false;
6386 r_refdef.scene.rtworldshadows = false;
6387 r_refdef.scene.rtdlight = false;
6388 r_refdef.scene.rtdlightshadows = false;
6389 r_refdef.lightmapintensity = 0;
6392 if (gamemode == GAME_NEHAHRA)
6394 if (gl_fogenable.integer)
6396 r_refdef.oldgl_fogenable = true;
6397 r_refdef.fog_density = gl_fogdensity.value;
6398 r_refdef.fog_red = gl_fogred.value;
6399 r_refdef.fog_green = gl_foggreen.value;
6400 r_refdef.fog_blue = gl_fogblue.value;
6401 r_refdef.fog_alpha = 1;
6402 r_refdef.fog_start = 0;
6403 r_refdef.fog_end = gl_skyclip.value;
6404 r_refdef.fog_height = 1<<30;
6405 r_refdef.fog_fadedepth = 128;
6407 else if (r_refdef.oldgl_fogenable)
6409 r_refdef.oldgl_fogenable = false;
6410 r_refdef.fog_density = 0;
6411 r_refdef.fog_red = 0;
6412 r_refdef.fog_green = 0;
6413 r_refdef.fog_blue = 0;
6414 r_refdef.fog_alpha = 0;
6415 r_refdef.fog_start = 0;
6416 r_refdef.fog_end = 0;
6417 r_refdef.fog_height = 1<<30;
6418 r_refdef.fog_fadedepth = 128;
6422 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6423 r_refdef.fog_start = max(0, r_refdef.fog_start);
6424 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6426 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6428 if (r_refdef.fog_density && r_drawfog.integer)
6430 r_refdef.fogenabled = true;
6431 // this is the point where the fog reaches 0.9986 alpha, which we
6432 // consider a good enough cutoff point for the texture
6433 // (0.9986 * 256 == 255.6)
6434 if (r_fog_exp2.integer)
6435 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6437 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6438 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6439 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6440 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6441 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6442 R_BuildFogHeightTexture();
6443 // fog color was already set
6444 // update the fog texture
6445 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)
6446 R_BuildFogTexture();
6447 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6448 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6451 r_refdef.fogenabled = false;
6453 switch(vid.renderpath)
6455 case RENDERPATH_GL20:
6456 case RENDERPATH_D3D9:
6457 case RENDERPATH_D3D10:
6458 case RENDERPATH_D3D11:
6459 case RENDERPATH_SOFT:
6460 case RENDERPATH_GLES2:
6461 if(v_glslgamma.integer && !vid_gammatables_trivial)
6463 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6465 // build GLSL gamma texture
6466 #define RAMPWIDTH 256
6467 unsigned short ramp[RAMPWIDTH * 3];
6468 unsigned char rampbgr[RAMPWIDTH][4];
6471 r_texture_gammaramps_serial = vid_gammatables_serial;
6473 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6474 for(i = 0; i < RAMPWIDTH; ++i)
6476 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6477 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6478 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6481 if (r_texture_gammaramps)
6483 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6487 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6493 // remove GLSL gamma texture
6496 case RENDERPATH_GL11:
6497 case RENDERPATH_GL13:
6498 case RENDERPATH_GLES1:
6503 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6504 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6510 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6511 if( scenetype != r_currentscenetype ) {
6512 // store the old scenetype
6513 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6514 r_currentscenetype = scenetype;
6515 // move in the new scene
6516 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6525 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6527 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6528 if( scenetype == r_currentscenetype ) {
6529 return &r_refdef.scene;
6531 return &r_scenes_store[ scenetype ];
6540 int dpsoftrast_test;
6541 void R_RenderView(void)
6543 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6545 dpsoftrast_test = r_test.integer;
6547 if (r_timereport_active)
6548 R_TimeReport("start");
6549 r_textureframe++; // used only by R_GetCurrentTexture
6550 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6552 if(R_CompileShader_CheckStaticParms())
6555 if (!r_drawentities.integer)
6556 r_refdef.scene.numentities = 0;
6558 R_AnimCache_ClearCache();
6559 R_FrameData_NewFrame();
6561 /* adjust for stereo display */
6562 if(R_Stereo_Active())
6564 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);
6565 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6568 if (r_refdef.view.isoverlay)
6570 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6571 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6572 R_TimeReport("depthclear");
6574 r_refdef.view.showdebug = false;
6576 r_waterstate.enabled = false;
6577 r_waterstate.numwaterplanes = 0;
6581 r_refdef.view.matrix = originalmatrix;
6587 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6589 r_refdef.view.matrix = originalmatrix;
6590 return; //Host_Error ("R_RenderView: NULL worldmodel");
6593 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6595 R_RenderView_UpdateViewVectors();
6597 R_Shadow_UpdateWorldLightSelection();
6599 R_Bloom_StartFrame();
6600 R_Water_StartFrame();
6603 if (r_timereport_active)
6604 R_TimeReport("viewsetup");
6606 R_ResetViewRendering3D();
6608 if (r_refdef.view.clear || r_refdef.fogenabled)
6610 R_ClearScreen(r_refdef.fogenabled);
6611 if (r_timereport_active)
6612 R_TimeReport("viewclear");
6614 r_refdef.view.clear = true;
6616 // this produces a bloom texture to be used in R_BlendView() later
6617 if (r_bloomstate.hdr)
6619 R_HDR_RenderBloomTexture();
6620 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6621 r_textureframe++; // used only by R_GetCurrentTexture
6624 r_refdef.view.showdebug = true;
6627 if (r_timereport_active)
6628 R_TimeReport("visibility");
6630 r_waterstate.numwaterplanes = 0;
6631 if (r_waterstate.enabled)
6632 R_RenderWaterPlanes();
6635 r_waterstate.numwaterplanes = 0;
6638 if (r_timereport_active)
6639 R_TimeReport("blendview");
6641 GL_Scissor(0, 0, vid.width, vid.height);
6642 GL_ScissorTest(false);
6644 r_refdef.view.matrix = originalmatrix;
6649 void R_RenderWaterPlanes(void)
6651 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6653 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6654 if (r_timereport_active)
6655 R_TimeReport("waterworld");
6658 // don't let sound skip if going slow
6659 if (r_refdef.scene.extraupdate)
6662 R_DrawModelsAddWaterPlanes();
6663 if (r_timereport_active)
6664 R_TimeReport("watermodels");
6666 if (r_waterstate.numwaterplanes)
6668 R_Water_ProcessPlanes();
6669 if (r_timereport_active)
6670 R_TimeReport("waterscenes");
6674 extern void R_DrawLightningBeams (void);
6675 extern void VM_CL_AddPolygonsToMeshQueue (void);
6676 extern void R_DrawPortals (void);
6677 extern cvar_t cl_locs_show;
6678 static void R_DrawLocs(void);
6679 static void R_DrawEntityBBoxes(void);
6680 static void R_DrawModelDecals(void);
6681 extern void R_DrawModelShadows(void);
6682 extern void R_DrawModelShadowMaps(void);
6683 extern cvar_t cl_decals_newsystem;
6684 extern qboolean r_shadow_usingdeferredprepass;
6685 void R_RenderScene(void)
6687 qboolean shadowmapping = false;
6689 if (r_timereport_active)
6690 R_TimeReport("beginscene");
6692 r_refdef.stats.renders++;
6696 // don't let sound skip if going slow
6697 if (r_refdef.scene.extraupdate)
6700 R_MeshQueue_BeginScene();
6704 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);
6706 if (r_timereport_active)
6707 R_TimeReport("skystartframe");
6709 if (cl.csqc_vidvars.drawworld)
6711 // don't let sound skip if going slow
6712 if (r_refdef.scene.extraupdate)
6715 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6717 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6718 if (r_timereport_active)
6719 R_TimeReport("worldsky");
6722 if (R_DrawBrushModelsSky() && r_timereport_active)
6723 R_TimeReport("bmodelsky");
6725 if (skyrendermasked && skyrenderlater)
6727 // we have to force off the water clipping plane while rendering sky
6731 if (r_timereport_active)
6732 R_TimeReport("sky");
6736 R_AnimCache_CacheVisibleEntities();
6737 if (r_timereport_active)
6738 R_TimeReport("animation");
6740 R_Shadow_PrepareLights();
6741 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6742 R_Shadow_PrepareModelShadows();
6743 if (r_timereport_active)
6744 R_TimeReport("preparelights");
6746 if (R_Shadow_ShadowMappingEnabled())
6747 shadowmapping = true;
6749 if (r_shadow_usingdeferredprepass)
6750 R_Shadow_DrawPrepass();
6752 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6754 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6755 if (r_timereport_active)
6756 R_TimeReport("worlddepth");
6758 if (r_depthfirst.integer >= 2)
6760 R_DrawModelsDepth();
6761 if (r_timereport_active)
6762 R_TimeReport("modeldepth");
6765 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6767 R_DrawModelShadowMaps();
6768 R_ResetViewRendering3D();
6769 // don't let sound skip if going slow
6770 if (r_refdef.scene.extraupdate)
6774 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6776 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6777 if (r_timereport_active)
6778 R_TimeReport("world");
6781 // don't let sound skip if going slow
6782 if (r_refdef.scene.extraupdate)
6786 if (r_timereport_active)
6787 R_TimeReport("models");
6789 // don't let sound skip if going slow
6790 if (r_refdef.scene.extraupdate)
6793 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6795 R_DrawModelShadows();
6796 R_ResetViewRendering3D();
6797 // don't let sound skip if going slow
6798 if (r_refdef.scene.extraupdate)
6802 if (!r_shadow_usingdeferredprepass)
6804 R_Shadow_DrawLights();
6805 if (r_timereport_active)
6806 R_TimeReport("rtlights");
6809 // don't let sound skip if going slow
6810 if (r_refdef.scene.extraupdate)
6813 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6815 R_DrawModelShadows();
6816 R_ResetViewRendering3D();
6817 // don't let sound skip if going slow
6818 if (r_refdef.scene.extraupdate)
6822 if (cl.csqc_vidvars.drawworld)
6824 if (cl_decals_newsystem.integer)
6826 R_DrawModelDecals();
6827 if (r_timereport_active)
6828 R_TimeReport("modeldecals");
6833 if (r_timereport_active)
6834 R_TimeReport("decals");
6838 if (r_timereport_active)
6839 R_TimeReport("particles");
6842 if (r_timereport_active)
6843 R_TimeReport("explosions");
6845 R_DrawLightningBeams();
6846 if (r_timereport_active)
6847 R_TimeReport("lightning");
6850 VM_CL_AddPolygonsToMeshQueue();
6852 if (r_refdef.view.showdebug)
6854 if (cl_locs_show.integer)
6857 if (r_timereport_active)
6858 R_TimeReport("showlocs");
6861 if (r_drawportals.integer)
6864 if (r_timereport_active)
6865 R_TimeReport("portals");
6868 if (r_showbboxes.value > 0)
6870 R_DrawEntityBBoxes();
6871 if (r_timereport_active)
6872 R_TimeReport("bboxes");
6876 if (r_transparent.integer)
6878 R_MeshQueue_RenderTransparent();
6879 if (r_timereport_active)
6880 R_TimeReport("drawtrans");
6883 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))
6885 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6886 if (r_timereport_active)
6887 R_TimeReport("worlddebug");
6888 R_DrawModelsDebug();
6889 if (r_timereport_active)
6890 R_TimeReport("modeldebug");
6893 if (cl.csqc_vidvars.drawworld)
6895 R_Shadow_DrawCoronas();
6896 if (r_timereport_active)
6897 R_TimeReport("coronas");
6902 GL_DepthTest(false);
6903 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6904 GL_Color(1, 1, 1, 1);
6905 qglBegin(GL_POLYGON);
6906 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6907 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6908 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6909 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6911 qglBegin(GL_POLYGON);
6912 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]);
6913 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]);
6914 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]);
6915 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]);
6917 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6921 // don't let sound skip if going slow
6922 if (r_refdef.scene.extraupdate)
6925 R_ResetViewRendering2D();
6928 static const unsigned short bboxelements[36] =
6938 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6941 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6943 RSurf_ActiveWorldEntity();
6945 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6946 GL_DepthMask(false);
6947 GL_DepthRange(0, 1);
6948 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6949 // R_Mesh_ResetTextureState();
6951 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6952 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6953 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6954 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6955 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6956 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6957 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6958 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6959 R_FillColors(color4f, 8, cr, cg, cb, ca);
6960 if (r_refdef.fogenabled)
6962 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6964 f1 = RSurf_FogVertex(v);
6966 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6967 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6968 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6971 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6972 R_Mesh_ResetTextureState();
6973 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6974 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6977 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6981 prvm_edict_t *edict;
6982 prvm_prog_t *prog_save = prog;
6984 // this function draws bounding boxes of server entities
6988 GL_CullFace(GL_NONE);
6989 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6993 for (i = 0;i < numsurfaces;i++)
6995 edict = PRVM_EDICT_NUM(surfacelist[i]);
6996 switch ((int)edict->fields.server->solid)
6998 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6999 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7000 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7001 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7002 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7003 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7005 color[3] *= r_showbboxes.value;
7006 color[3] = bound(0, color[3], 1);
7007 GL_DepthTest(!r_showdisabledepthtest.integer);
7008 GL_CullFace(r_refdef.view.cullface_front);
7009 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7015 static void R_DrawEntityBBoxes(void)
7018 prvm_edict_t *edict;
7020 prvm_prog_t *prog_save = prog;
7022 // this function draws bounding boxes of server entities
7028 for (i = 0;i < prog->num_edicts;i++)
7030 edict = PRVM_EDICT_NUM(i);
7031 if (edict->priv.server->free)
7033 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7034 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7036 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7038 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7039 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7045 static const int nomodelelement3i[24] =
7057 static const unsigned short nomodelelement3s[24] =
7069 static const float nomodelvertex3f[6*3] =
7079 static const float nomodelcolor4f[6*4] =
7081 0.0f, 0.0f, 0.5f, 1.0f,
7082 0.0f, 0.0f, 0.5f, 1.0f,
7083 0.0f, 0.5f, 0.0f, 1.0f,
7084 0.0f, 0.5f, 0.0f, 1.0f,
7085 0.5f, 0.0f, 0.0f, 1.0f,
7086 0.5f, 0.0f, 0.0f, 1.0f
7089 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7095 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);
7097 // this is only called once per entity so numsurfaces is always 1, and
7098 // surfacelist is always {0}, so this code does not handle batches
7100 if (rsurface.ent_flags & RENDER_ADDITIVE)
7102 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7103 GL_DepthMask(false);
7105 else if (rsurface.colormod[3] < 1)
7107 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7108 GL_DepthMask(false);
7112 GL_BlendFunc(GL_ONE, GL_ZERO);
7115 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7116 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7117 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7118 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7119 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7120 for (i = 0, c = color4f;i < 6;i++, c += 4)
7122 c[0] *= rsurface.colormod[0];
7123 c[1] *= rsurface.colormod[1];
7124 c[2] *= rsurface.colormod[2];
7125 c[3] *= rsurface.colormod[3];
7127 if (r_refdef.fogenabled)
7129 for (i = 0, c = color4f;i < 6;i++, c += 4)
7131 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7133 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7134 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7135 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7138 // R_Mesh_ResetTextureState();
7139 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7140 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7141 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7144 void R_DrawNoModel(entity_render_t *ent)
7147 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7148 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7149 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7151 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7154 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7156 vec3_t right1, right2, diff, normal;
7158 VectorSubtract (org2, org1, normal);
7160 // calculate 'right' vector for start
7161 VectorSubtract (r_refdef.view.origin, org1, diff);
7162 CrossProduct (normal, diff, right1);
7163 VectorNormalize (right1);
7165 // calculate 'right' vector for end
7166 VectorSubtract (r_refdef.view.origin, org2, diff);
7167 CrossProduct (normal, diff, right2);
7168 VectorNormalize (right2);
7170 vert[ 0] = org1[0] + width * right1[0];
7171 vert[ 1] = org1[1] + width * right1[1];
7172 vert[ 2] = org1[2] + width * right1[2];
7173 vert[ 3] = org1[0] - width * right1[0];
7174 vert[ 4] = org1[1] - width * right1[1];
7175 vert[ 5] = org1[2] - width * right1[2];
7176 vert[ 6] = org2[0] - width * right2[0];
7177 vert[ 7] = org2[1] - width * right2[1];
7178 vert[ 8] = org2[2] - width * right2[2];
7179 vert[ 9] = org2[0] + width * right2[0];
7180 vert[10] = org2[1] + width * right2[1];
7181 vert[11] = org2[2] + width * right2[2];
7184 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)
7186 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7187 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7188 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7189 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7190 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7191 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7192 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7193 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7194 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7195 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7196 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7197 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7200 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7205 VectorSet(v, x, y, z);
7206 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7207 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7209 if (i == mesh->numvertices)
7211 if (mesh->numvertices < mesh->maxvertices)
7213 VectorCopy(v, vertex3f);
7214 mesh->numvertices++;
7216 return mesh->numvertices;
7222 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7226 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7227 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7228 e = mesh->element3i + mesh->numtriangles * 3;
7229 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7231 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7232 if (mesh->numtriangles < mesh->maxtriangles)
7237 mesh->numtriangles++;
7239 element[1] = element[2];
7243 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7247 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7248 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7249 e = mesh->element3i + mesh->numtriangles * 3;
7250 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7252 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7253 if (mesh->numtriangles < mesh->maxtriangles)
7258 mesh->numtriangles++;
7260 element[1] = element[2];
7264 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7265 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7267 int planenum, planenum2;
7270 mplane_t *plane, *plane2;
7272 double temppoints[2][256*3];
7273 // figure out how large a bounding box we need to properly compute this brush
7275 for (w = 0;w < numplanes;w++)
7276 maxdist = max(maxdist, fabs(planes[w].dist));
7277 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7278 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7279 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7283 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7284 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7286 if (planenum2 == planenum)
7288 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);
7291 if (tempnumpoints < 3)
7293 // generate elements forming a triangle fan for this polygon
7294 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7298 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)
7300 texturelayer_t *layer;
7301 layer = t->currentlayers + t->currentnumlayers++;
7303 layer->depthmask = depthmask;
7304 layer->blendfunc1 = blendfunc1;
7305 layer->blendfunc2 = blendfunc2;
7306 layer->texture = texture;
7307 layer->texmatrix = *matrix;
7308 layer->color[0] = r;
7309 layer->color[1] = g;
7310 layer->color[2] = b;
7311 layer->color[3] = a;
7314 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7316 if(parms[0] == 0 && parms[1] == 0)
7318 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7319 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7324 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7327 index = parms[2] + r_refdef.scene.time * parms[3];
7328 index -= floor(index);
7329 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7332 case Q3WAVEFUNC_NONE:
7333 case Q3WAVEFUNC_NOISE:
7334 case Q3WAVEFUNC_COUNT:
7337 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7338 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7339 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7340 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7341 case Q3WAVEFUNC_TRIANGLE:
7343 f = index - floor(index);
7354 f = parms[0] + parms[1] * f;
7355 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7356 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7360 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7365 matrix4x4_t matrix, temp;
7366 switch(tcmod->tcmod)
7370 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7371 matrix = r_waterscrollmatrix;
7373 matrix = identitymatrix;
7375 case Q3TCMOD_ENTITYTRANSLATE:
7376 // this is used in Q3 to allow the gamecode to control texcoord
7377 // scrolling on the entity, which is not supported in darkplaces yet.
7378 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7380 case Q3TCMOD_ROTATE:
7381 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7382 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7383 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7386 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7388 case Q3TCMOD_SCROLL:
7389 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7391 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7392 w = (int) tcmod->parms[0];
7393 h = (int) tcmod->parms[1];
7394 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7396 idx = (int) floor(f * w * h);
7397 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7399 case Q3TCMOD_STRETCH:
7400 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7401 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7403 case Q3TCMOD_TRANSFORM:
7404 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7405 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7406 VectorSet(tcmat + 6, 0 , 0 , 1);
7407 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7408 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7410 case Q3TCMOD_TURBULENT:
7411 // this is handled in the RSurf_PrepareVertices function
7412 matrix = identitymatrix;
7416 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7419 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7421 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7422 char name[MAX_QPATH];
7423 skinframe_t *skinframe;
7424 unsigned char pixels[296*194];
7425 strlcpy(cache->name, skinname, sizeof(cache->name));
7426 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7427 if (developer_loading.integer)
7428 Con_Printf("loading %s\n", name);
7429 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7430 if (!skinframe || !skinframe->base)
7433 fs_offset_t filesize;
7435 f = FS_LoadFile(name, tempmempool, true, &filesize);
7438 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7439 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7443 cache->skinframe = skinframe;
7446 texture_t *R_GetCurrentTexture(texture_t *t)
7449 const entity_render_t *ent = rsurface.entity;
7450 dp_model_t *model = ent->model;
7451 q3shaderinfo_layer_tcmod_t *tcmod;
7453 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7454 return t->currentframe;
7455 t->update_lastrenderframe = r_textureframe;
7456 t->update_lastrenderentity = (void *)ent;
7458 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7459 t->camera_entity = ent->entitynumber;
7461 t->camera_entity = 0;
7463 // switch to an alternate material if this is a q1bsp animated material
7465 texture_t *texture = t;
7466 int s = rsurface.ent_skinnum;
7467 if ((unsigned int)s >= (unsigned int)model->numskins)
7469 if (model->skinscenes)
7471 if (model->skinscenes[s].framecount > 1)
7472 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7474 s = model->skinscenes[s].firstframe;
7477 t = t + s * model->num_surfaces;
7480 // use an alternate animation if the entity's frame is not 0,
7481 // and only if the texture has an alternate animation
7482 if (rsurface.ent_alttextures && t->anim_total[1])
7483 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7485 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7487 texture->currentframe = t;
7490 // update currentskinframe to be a qw skin or animation frame
7491 if (rsurface.ent_qwskin >= 0)
7493 i = rsurface.ent_qwskin;
7494 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7496 r_qwskincache_size = cl.maxclients;
7498 Mem_Free(r_qwskincache);
7499 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7501 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7502 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7503 t->currentskinframe = r_qwskincache[i].skinframe;
7504 if (t->currentskinframe == NULL)
7505 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7507 else if (t->numskinframes >= 2)
7508 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7509 if (t->backgroundnumskinframes >= 2)
7510 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7512 t->currentmaterialflags = t->basematerialflags;
7513 t->currentalpha = rsurface.colormod[3];
7514 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7515 t->currentalpha *= r_wateralpha.value;
7516 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7517 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7518 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7519 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7520 if (!(rsurface.ent_flags & RENDER_LIGHT))
7521 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7522 else if (FAKELIGHT_ENABLED)
7524 // no modellight if using fakelight for the map
7526 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7528 // pick a model lighting mode
7529 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7530 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7532 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7534 if (rsurface.ent_flags & RENDER_ADDITIVE)
7535 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7536 else if (t->currentalpha < 1)
7537 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7538 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7539 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7540 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7541 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7542 if (t->backgroundnumskinframes)
7543 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7544 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7546 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7547 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7550 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7551 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7552 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7554 // there is no tcmod
7555 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7557 t->currenttexmatrix = r_waterscrollmatrix;
7558 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7560 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7562 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7563 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7566 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7567 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7568 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7569 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7571 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7572 if (t->currentskinframe->qpixels)
7573 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7574 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7575 if (!t->basetexture)
7576 t->basetexture = r_texture_notexture;
7577 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7578 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7579 t->nmaptexture = t->currentskinframe->nmap;
7580 if (!t->nmaptexture)
7581 t->nmaptexture = r_texture_blanknormalmap;
7582 t->glosstexture = r_texture_black;
7583 t->glowtexture = t->currentskinframe->glow;
7584 t->fogtexture = t->currentskinframe->fog;
7585 t->reflectmasktexture = t->currentskinframe->reflect;
7586 if (t->backgroundnumskinframes)
7588 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7589 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7590 t->backgroundglosstexture = r_texture_black;
7591 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7592 if (!t->backgroundnmaptexture)
7593 t->backgroundnmaptexture = r_texture_blanknormalmap;
7597 t->backgroundbasetexture = r_texture_white;
7598 t->backgroundnmaptexture = r_texture_blanknormalmap;
7599 t->backgroundglosstexture = r_texture_black;
7600 t->backgroundglowtexture = NULL;
7602 t->specularpower = r_shadow_glossexponent.value;
7603 // TODO: store reference values for these in the texture?
7604 t->specularscale = 0;
7605 if (r_shadow_gloss.integer > 0)
7607 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7609 if (r_shadow_glossintensity.value > 0)
7611 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7612 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7613 t->specularscale = r_shadow_glossintensity.value;
7616 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7618 t->glosstexture = r_texture_white;
7619 t->backgroundglosstexture = r_texture_white;
7620 t->specularscale = r_shadow_gloss2intensity.value;
7621 t->specularpower = r_shadow_gloss2exponent.value;
7624 t->specularscale *= t->specularscalemod;
7625 t->specularpower *= t->specularpowermod;
7627 // lightmaps mode looks bad with dlights using actual texturing, so turn
7628 // off the colormap and glossmap, but leave the normalmap on as it still
7629 // accurately represents the shading involved
7630 if (gl_lightmaps.integer)
7632 t->basetexture = r_texture_grey128;
7633 t->pantstexture = r_texture_black;
7634 t->shirttexture = r_texture_black;
7635 t->nmaptexture = r_texture_blanknormalmap;
7636 t->glosstexture = r_texture_black;
7637 t->glowtexture = NULL;
7638 t->fogtexture = NULL;
7639 t->reflectmasktexture = NULL;
7640 t->backgroundbasetexture = NULL;
7641 t->backgroundnmaptexture = r_texture_blanknormalmap;
7642 t->backgroundglosstexture = r_texture_black;
7643 t->backgroundglowtexture = NULL;
7644 t->specularscale = 0;
7645 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7648 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7649 VectorClear(t->dlightcolor);
7650 t->currentnumlayers = 0;
7651 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7653 int blendfunc1, blendfunc2;
7655 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7657 blendfunc1 = GL_SRC_ALPHA;
7658 blendfunc2 = GL_ONE;
7660 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7662 blendfunc1 = GL_SRC_ALPHA;
7663 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7665 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7667 blendfunc1 = t->customblendfunc[0];
7668 blendfunc2 = t->customblendfunc[1];
7672 blendfunc1 = GL_ONE;
7673 blendfunc2 = GL_ZERO;
7675 // don't colormod evilblend textures
7676 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7677 VectorSet(t->lightmapcolor, 1, 1, 1);
7678 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7679 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7681 // fullbright is not affected by r_refdef.lightmapintensity
7682 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]);
7683 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7684 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]);
7685 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7686 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]);
7690 vec3_t ambientcolor;
7692 // set the color tint used for lights affecting this surface
7693 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7695 // q3bsp has no lightmap updates, so the lightstylevalue that
7696 // would normally be baked into the lightmap must be
7697 // applied to the color
7698 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7699 if (model->type == mod_brushq3)
7700 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7701 colorscale *= r_refdef.lightmapintensity;
7702 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7703 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7704 // basic lit geometry
7705 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]);
7706 // add pants/shirt if needed
7707 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7708 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]);
7709 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7710 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]);
7711 // now add ambient passes if needed
7712 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7714 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]);
7715 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7716 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]);
7717 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7718 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]);
7721 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7722 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]);
7723 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7725 // if this is opaque use alpha blend which will darken the earlier
7728 // if this is an alpha blended material, all the earlier passes
7729 // were darkened by fog already, so we only need to add the fog
7730 // color ontop through the fog mask texture
7732 // if this is an additive blended material, all the earlier passes
7733 // were darkened by fog already, and we should not add fog color
7734 // (because the background was not darkened, there is no fog color
7735 // that was lost behind it).
7736 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]);
7740 return t->currentframe;
7743 rsurfacestate_t rsurface;
7745 void RSurf_ActiveWorldEntity(void)
7747 dp_model_t *model = r_refdef.scene.worldmodel;
7748 //if (rsurface.entity == r_refdef.scene.worldentity)
7750 rsurface.entity = r_refdef.scene.worldentity;
7751 rsurface.skeleton = NULL;
7752 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7753 rsurface.ent_skinnum = 0;
7754 rsurface.ent_qwskin = -1;
7755 rsurface.ent_shadertime = 0;
7756 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7757 rsurface.matrix = identitymatrix;
7758 rsurface.inversematrix = identitymatrix;
7759 rsurface.matrixscale = 1;
7760 rsurface.inversematrixscale = 1;
7761 R_EntityMatrix(&identitymatrix);
7762 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7763 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7764 rsurface.fograngerecip = r_refdef.fograngerecip;
7765 rsurface.fogheightfade = r_refdef.fogheightfade;
7766 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7767 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7768 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7769 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7770 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7771 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7772 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7773 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7774 rsurface.colormod[3] = 1;
7775 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);
7776 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7777 rsurface.frameblend[0].lerp = 1;
7778 rsurface.ent_alttextures = false;
7779 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7780 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7781 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7782 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7783 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7784 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7785 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7786 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7787 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7788 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7789 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7790 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7791 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7792 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7793 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7794 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7795 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7796 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7797 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7798 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7799 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7800 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7801 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7802 rsurface.modelelement3i = model->surfmesh.data_element3i;
7803 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7804 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7805 rsurface.modelelement3s = model->surfmesh.data_element3s;
7806 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7807 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7808 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7809 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7810 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7811 rsurface.modelsurfaces = model->data_surfaces;
7812 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7813 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7814 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7815 rsurface.modelgeneratedvertex = false;
7816 rsurface.batchgeneratedvertex = false;
7817 rsurface.batchfirstvertex = 0;
7818 rsurface.batchnumvertices = 0;
7819 rsurface.batchfirsttriangle = 0;
7820 rsurface.batchnumtriangles = 0;
7821 rsurface.batchvertex3f = NULL;
7822 rsurface.batchvertex3f_vertexbuffer = NULL;
7823 rsurface.batchvertex3f_bufferoffset = 0;
7824 rsurface.batchsvector3f = NULL;
7825 rsurface.batchsvector3f_vertexbuffer = NULL;
7826 rsurface.batchsvector3f_bufferoffset = 0;
7827 rsurface.batchtvector3f = NULL;
7828 rsurface.batchtvector3f_vertexbuffer = NULL;
7829 rsurface.batchtvector3f_bufferoffset = 0;
7830 rsurface.batchnormal3f = NULL;
7831 rsurface.batchnormal3f_vertexbuffer = NULL;
7832 rsurface.batchnormal3f_bufferoffset = 0;
7833 rsurface.batchlightmapcolor4f = NULL;
7834 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7835 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7836 rsurface.batchtexcoordtexture2f = NULL;
7837 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7838 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7839 rsurface.batchtexcoordlightmap2f = NULL;
7840 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7841 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7842 rsurface.batchvertexmesh = NULL;
7843 rsurface.batchvertexmeshbuffer = NULL;
7844 rsurface.batchvertex3fbuffer = NULL;
7845 rsurface.batchelement3i = NULL;
7846 rsurface.batchelement3i_indexbuffer = NULL;
7847 rsurface.batchelement3i_bufferoffset = 0;
7848 rsurface.batchelement3s = NULL;
7849 rsurface.batchelement3s_indexbuffer = NULL;
7850 rsurface.batchelement3s_bufferoffset = 0;
7851 rsurface.passcolor4f = NULL;
7852 rsurface.passcolor4f_vertexbuffer = NULL;
7853 rsurface.passcolor4f_bufferoffset = 0;
7856 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7858 dp_model_t *model = ent->model;
7859 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7861 rsurface.entity = (entity_render_t *)ent;
7862 rsurface.skeleton = ent->skeleton;
7863 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7864 rsurface.ent_skinnum = ent->skinnum;
7865 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;
7866 rsurface.ent_shadertime = ent->shadertime;
7867 rsurface.ent_flags = ent->flags;
7868 rsurface.matrix = ent->matrix;
7869 rsurface.inversematrix = ent->inversematrix;
7870 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7871 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7872 R_EntityMatrix(&rsurface.matrix);
7873 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7874 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7875 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7876 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7877 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7878 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7879 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7880 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7881 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7882 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7883 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7884 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7885 rsurface.colormod[3] = ent->alpha;
7886 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7887 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7888 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7889 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7890 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7891 if (ent->model->brush.submodel && !prepass)
7893 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7894 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7896 if (model->surfmesh.isanimated && model->AnimateVertices)
7898 if (ent->animcache_vertex3f)
7900 rsurface.modelvertex3f = ent->animcache_vertex3f;
7901 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7902 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7903 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7904 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7905 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7906 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7908 else if (wanttangents)
7910 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7911 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7912 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7913 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7914 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7915 rsurface.modelvertexmesh = NULL;
7916 rsurface.modelvertexmeshbuffer = NULL;
7917 rsurface.modelvertex3fbuffer = NULL;
7919 else if (wantnormals)
7921 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7922 rsurface.modelsvector3f = NULL;
7923 rsurface.modeltvector3f = NULL;
7924 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7925 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7926 rsurface.modelvertexmesh = NULL;
7927 rsurface.modelvertexmeshbuffer = NULL;
7928 rsurface.modelvertex3fbuffer = NULL;
7932 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7933 rsurface.modelsvector3f = NULL;
7934 rsurface.modeltvector3f = NULL;
7935 rsurface.modelnormal3f = NULL;
7936 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7937 rsurface.modelvertexmesh = NULL;
7938 rsurface.modelvertexmeshbuffer = NULL;
7939 rsurface.modelvertex3fbuffer = NULL;
7941 rsurface.modelvertex3f_vertexbuffer = 0;
7942 rsurface.modelvertex3f_bufferoffset = 0;
7943 rsurface.modelsvector3f_vertexbuffer = 0;
7944 rsurface.modelsvector3f_bufferoffset = 0;
7945 rsurface.modeltvector3f_vertexbuffer = 0;
7946 rsurface.modeltvector3f_bufferoffset = 0;
7947 rsurface.modelnormal3f_vertexbuffer = 0;
7948 rsurface.modelnormal3f_bufferoffset = 0;
7949 rsurface.modelgeneratedvertex = true;
7953 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7954 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7955 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7956 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7957 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7958 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7959 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7960 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7961 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7962 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7963 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7964 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7965 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7966 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7967 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7968 rsurface.modelgeneratedvertex = false;
7970 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7971 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7972 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7973 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7974 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7975 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7976 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7977 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7978 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7979 rsurface.modelelement3i = model->surfmesh.data_element3i;
7980 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7981 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7982 rsurface.modelelement3s = model->surfmesh.data_element3s;
7983 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7984 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7985 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7986 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7987 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7988 rsurface.modelsurfaces = model->data_surfaces;
7989 rsurface.batchgeneratedvertex = false;
7990 rsurface.batchfirstvertex = 0;
7991 rsurface.batchnumvertices = 0;
7992 rsurface.batchfirsttriangle = 0;
7993 rsurface.batchnumtriangles = 0;
7994 rsurface.batchvertex3f = NULL;
7995 rsurface.batchvertex3f_vertexbuffer = NULL;
7996 rsurface.batchvertex3f_bufferoffset = 0;
7997 rsurface.batchsvector3f = NULL;
7998 rsurface.batchsvector3f_vertexbuffer = NULL;
7999 rsurface.batchsvector3f_bufferoffset = 0;
8000 rsurface.batchtvector3f = NULL;
8001 rsurface.batchtvector3f_vertexbuffer = NULL;
8002 rsurface.batchtvector3f_bufferoffset = 0;
8003 rsurface.batchnormal3f = NULL;
8004 rsurface.batchnormal3f_vertexbuffer = NULL;
8005 rsurface.batchnormal3f_bufferoffset = 0;
8006 rsurface.batchlightmapcolor4f = NULL;
8007 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8008 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8009 rsurface.batchtexcoordtexture2f = NULL;
8010 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8011 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8012 rsurface.batchtexcoordlightmap2f = NULL;
8013 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8014 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8015 rsurface.batchvertexmesh = NULL;
8016 rsurface.batchvertexmeshbuffer = NULL;
8017 rsurface.batchvertex3fbuffer = NULL;
8018 rsurface.batchelement3i = NULL;
8019 rsurface.batchelement3i_indexbuffer = NULL;
8020 rsurface.batchelement3i_bufferoffset = 0;
8021 rsurface.batchelement3s = NULL;
8022 rsurface.batchelement3s_indexbuffer = NULL;
8023 rsurface.batchelement3s_bufferoffset = 0;
8024 rsurface.passcolor4f = NULL;
8025 rsurface.passcolor4f_vertexbuffer = NULL;
8026 rsurface.passcolor4f_bufferoffset = 0;
8029 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)
8031 rsurface.entity = r_refdef.scene.worldentity;
8032 rsurface.skeleton = NULL;
8033 rsurface.ent_skinnum = 0;
8034 rsurface.ent_qwskin = -1;
8035 rsurface.ent_shadertime = shadertime;
8036 rsurface.ent_flags = entflags;
8037 rsurface.modelnumvertices = numvertices;
8038 rsurface.modelnumtriangles = numtriangles;
8039 rsurface.matrix = *matrix;
8040 rsurface.inversematrix = *inversematrix;
8041 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8042 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8043 R_EntityMatrix(&rsurface.matrix);
8044 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8045 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8046 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8047 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8048 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8049 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8050 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8051 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8052 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8053 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8054 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8055 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8056 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);
8057 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8058 rsurface.frameblend[0].lerp = 1;
8059 rsurface.ent_alttextures = false;
8060 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8061 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8064 rsurface.modelvertex3f = (float *)vertex3f;
8065 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8066 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8067 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8069 else if (wantnormals)
8071 rsurface.modelvertex3f = (float *)vertex3f;
8072 rsurface.modelsvector3f = NULL;
8073 rsurface.modeltvector3f = NULL;
8074 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8078 rsurface.modelvertex3f = (float *)vertex3f;
8079 rsurface.modelsvector3f = NULL;
8080 rsurface.modeltvector3f = NULL;
8081 rsurface.modelnormal3f = NULL;
8083 rsurface.modelvertexmesh = NULL;
8084 rsurface.modelvertexmeshbuffer = NULL;
8085 rsurface.modelvertex3fbuffer = NULL;
8086 rsurface.modelvertex3f_vertexbuffer = 0;
8087 rsurface.modelvertex3f_bufferoffset = 0;
8088 rsurface.modelsvector3f_vertexbuffer = 0;
8089 rsurface.modelsvector3f_bufferoffset = 0;
8090 rsurface.modeltvector3f_vertexbuffer = 0;
8091 rsurface.modeltvector3f_bufferoffset = 0;
8092 rsurface.modelnormal3f_vertexbuffer = 0;
8093 rsurface.modelnormal3f_bufferoffset = 0;
8094 rsurface.modelgeneratedvertex = true;
8095 rsurface.modellightmapcolor4f = (float *)color4f;
8096 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8097 rsurface.modellightmapcolor4f_bufferoffset = 0;
8098 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8099 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8100 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8101 rsurface.modeltexcoordlightmap2f = NULL;
8102 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8103 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8104 rsurface.modelelement3i = (int *)element3i;
8105 rsurface.modelelement3i_indexbuffer = NULL;
8106 rsurface.modelelement3i_bufferoffset = 0;
8107 rsurface.modelelement3s = (unsigned short *)element3s;
8108 rsurface.modelelement3s_indexbuffer = NULL;
8109 rsurface.modelelement3s_bufferoffset = 0;
8110 rsurface.modellightmapoffsets = NULL;
8111 rsurface.modelsurfaces = NULL;
8112 rsurface.batchgeneratedvertex = false;
8113 rsurface.batchfirstvertex = 0;
8114 rsurface.batchnumvertices = 0;
8115 rsurface.batchfirsttriangle = 0;
8116 rsurface.batchnumtriangles = 0;
8117 rsurface.batchvertex3f = NULL;
8118 rsurface.batchvertex3f_vertexbuffer = NULL;
8119 rsurface.batchvertex3f_bufferoffset = 0;
8120 rsurface.batchsvector3f = NULL;
8121 rsurface.batchsvector3f_vertexbuffer = NULL;
8122 rsurface.batchsvector3f_bufferoffset = 0;
8123 rsurface.batchtvector3f = NULL;
8124 rsurface.batchtvector3f_vertexbuffer = NULL;
8125 rsurface.batchtvector3f_bufferoffset = 0;
8126 rsurface.batchnormal3f = NULL;
8127 rsurface.batchnormal3f_vertexbuffer = NULL;
8128 rsurface.batchnormal3f_bufferoffset = 0;
8129 rsurface.batchlightmapcolor4f = NULL;
8130 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8131 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8132 rsurface.batchtexcoordtexture2f = NULL;
8133 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8134 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8135 rsurface.batchtexcoordlightmap2f = NULL;
8136 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8137 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8138 rsurface.batchvertexmesh = NULL;
8139 rsurface.batchvertexmeshbuffer = NULL;
8140 rsurface.batchvertex3fbuffer = NULL;
8141 rsurface.batchelement3i = NULL;
8142 rsurface.batchelement3i_indexbuffer = NULL;
8143 rsurface.batchelement3i_bufferoffset = 0;
8144 rsurface.batchelement3s = NULL;
8145 rsurface.batchelement3s_indexbuffer = NULL;
8146 rsurface.batchelement3s_bufferoffset = 0;
8147 rsurface.passcolor4f = NULL;
8148 rsurface.passcolor4f_vertexbuffer = NULL;
8149 rsurface.passcolor4f_bufferoffset = 0;
8151 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8153 if ((wantnormals || wanttangents) && !normal3f)
8155 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8156 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8158 if (wanttangents && !svector3f)
8160 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8161 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8162 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8167 float RSurf_FogPoint(const float *v)
8169 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8170 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8171 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8172 float FogHeightFade = r_refdef.fogheightfade;
8174 unsigned int fogmasktableindex;
8175 if (r_refdef.fogplaneviewabove)
8176 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8178 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8179 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8180 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8183 float RSurf_FogVertex(const float *v)
8185 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8186 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8187 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8188 float FogHeightFade = rsurface.fogheightfade;
8190 unsigned int fogmasktableindex;
8191 if (r_refdef.fogplaneviewabove)
8192 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8194 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8195 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8196 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8199 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8202 for (i = 0;i < numelements;i++)
8203 outelement3i[i] = inelement3i[i] + adjust;
8206 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8207 extern cvar_t gl_vbo;
8208 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8216 int surfacefirsttriangle;
8217 int surfacenumtriangles;
8218 int surfacefirstvertex;
8219 int surfaceendvertex;
8220 int surfacenumvertices;
8221 int batchnumvertices;
8222 int batchnumtriangles;
8226 qboolean dynamicvertex;
8230 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8232 q3shaderinfo_deform_t *deform;
8233 const msurface_t *surface, *firstsurface;
8234 r_vertexmesh_t *vertexmesh;
8235 if (!texturenumsurfaces)
8237 // find vertex range of this surface batch
8239 firstsurface = texturesurfacelist[0];
8240 firsttriangle = firstsurface->num_firsttriangle;
8241 batchnumvertices = 0;
8242 batchnumtriangles = 0;
8243 firstvertex = endvertex = firstsurface->num_firstvertex;
8244 for (i = 0;i < texturenumsurfaces;i++)
8246 surface = texturesurfacelist[i];
8247 if (surface != firstsurface + i)
8249 surfacefirstvertex = surface->num_firstvertex;
8250 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8251 surfacenumvertices = surface->num_vertices;
8252 surfacenumtriangles = surface->num_triangles;
8253 if (firstvertex > surfacefirstvertex)
8254 firstvertex = surfacefirstvertex;
8255 if (endvertex < surfaceendvertex)
8256 endvertex = surfaceendvertex;
8257 batchnumvertices += surfacenumvertices;
8258 batchnumtriangles += surfacenumtriangles;
8261 // we now know the vertex range used, and if there are any gaps in it
8262 rsurface.batchfirstvertex = firstvertex;
8263 rsurface.batchnumvertices = endvertex - firstvertex;
8264 rsurface.batchfirsttriangle = firsttriangle;
8265 rsurface.batchnumtriangles = batchnumtriangles;
8267 // this variable holds flags for which properties have been updated that
8268 // may require regenerating vertexmesh array...
8271 // check if any dynamic vertex processing must occur
8272 dynamicvertex = false;
8274 // if there is a chance of animated vertex colors, it's a dynamic batch
8275 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8277 dynamicvertex = true;
8278 batchneed |= BATCHNEED_NOGAPS;
8279 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8282 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8284 switch (deform->deform)
8287 case Q3DEFORM_PROJECTIONSHADOW:
8288 case Q3DEFORM_TEXT0:
8289 case Q3DEFORM_TEXT1:
8290 case Q3DEFORM_TEXT2:
8291 case Q3DEFORM_TEXT3:
8292 case Q3DEFORM_TEXT4:
8293 case Q3DEFORM_TEXT5:
8294 case Q3DEFORM_TEXT6:
8295 case Q3DEFORM_TEXT7:
8298 case Q3DEFORM_AUTOSPRITE:
8299 dynamicvertex = true;
8300 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8301 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8303 case Q3DEFORM_AUTOSPRITE2:
8304 dynamicvertex = true;
8305 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8306 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8308 case Q3DEFORM_NORMAL:
8309 dynamicvertex = true;
8310 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8311 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8314 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8315 break; // if wavefunc is a nop, ignore this transform
8316 dynamicvertex = true;
8317 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8318 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8320 case Q3DEFORM_BULGE:
8321 dynamicvertex = true;
8322 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8323 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8326 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8327 break; // if wavefunc is a nop, ignore this transform
8328 dynamicvertex = true;
8329 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8330 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8334 switch(rsurface.texture->tcgen.tcgen)
8337 case Q3TCGEN_TEXTURE:
8339 case Q3TCGEN_LIGHTMAP:
8340 dynamicvertex = true;
8341 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8342 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8344 case Q3TCGEN_VECTOR:
8345 dynamicvertex = true;
8346 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8347 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8349 case Q3TCGEN_ENVIRONMENT:
8350 dynamicvertex = true;
8351 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8352 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8355 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8357 dynamicvertex = true;
8358 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8359 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8362 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8364 dynamicvertex = true;
8365 batchneed |= BATCHNEED_NOGAPS;
8366 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8369 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8371 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8372 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8373 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8374 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8375 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8376 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8377 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8380 // when the model data has no vertex buffer (dynamic mesh), we need to
8382 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8383 batchneed |= BATCHNEED_NOGAPS;
8385 // if needsupdate, we have to do a dynamic vertex batch for sure
8386 if (needsupdate & batchneed)
8387 dynamicvertex = true;
8389 // see if we need to build vertexmesh from arrays
8390 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8391 dynamicvertex = true;
8393 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8394 // also some drivers strongly dislike firstvertex
8395 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8396 dynamicvertex = true;
8398 rsurface.batchvertex3f = rsurface.modelvertex3f;
8399 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8400 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8401 rsurface.batchsvector3f = rsurface.modelsvector3f;
8402 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8403 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8404 rsurface.batchtvector3f = rsurface.modeltvector3f;
8405 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8406 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8407 rsurface.batchnormal3f = rsurface.modelnormal3f;
8408 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8409 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8410 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8411 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8412 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8413 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8414 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8415 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8416 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8417 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8418 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8419 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8420 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8421 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8422 rsurface.batchelement3i = rsurface.modelelement3i;
8423 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8424 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8425 rsurface.batchelement3s = rsurface.modelelement3s;
8426 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8427 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8429 // if any dynamic vertex processing has to occur in software, we copy the
8430 // entire surface list together before processing to rebase the vertices
8431 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8433 // if any gaps exist and we do not have a static vertex buffer, we have to
8434 // copy the surface list together to avoid wasting upload bandwidth on the
8435 // vertices in the gaps.
8437 // if gaps exist and we have a static vertex buffer, we still have to
8438 // combine the index buffer ranges into one dynamic index buffer.
8440 // in all cases we end up with data that can be drawn in one call.
8444 // static vertex data, just set pointers...
8445 rsurface.batchgeneratedvertex = false;
8446 // if there are gaps, we want to build a combined index buffer,
8447 // otherwise use the original static buffer with an appropriate offset
8450 // build a new triangle elements array for this batch
8451 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8452 rsurface.batchfirsttriangle = 0;
8454 for (i = 0;i < texturenumsurfaces;i++)
8456 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8457 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8458 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8459 numtriangles += surfacenumtriangles;
8461 rsurface.batchelement3i_indexbuffer = NULL;
8462 rsurface.batchelement3i_bufferoffset = 0;
8463 rsurface.batchelement3s = NULL;
8464 rsurface.batchelement3s_indexbuffer = NULL;
8465 rsurface.batchelement3s_bufferoffset = 0;
8466 if (endvertex <= 65536)
8468 // make a 16bit (unsigned short) index array if possible
8469 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8470 for (i = 0;i < numtriangles*3;i++)
8471 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8477 // something needs software processing, do it for real...
8478 // we only directly handle separate array data in this case and then
8479 // generate interleaved data if needed...
8480 rsurface.batchgeneratedvertex = true;
8482 // now copy the vertex data into a combined array and make an index array
8483 // (this is what Quake3 does all the time)
8484 //if (gaps || rsurface.batchfirstvertex)
8486 rsurface.batchvertex3fbuffer = NULL;
8487 rsurface.batchvertexmesh = NULL;
8488 rsurface.batchvertexmeshbuffer = NULL;
8489 rsurface.batchvertex3f = NULL;
8490 rsurface.batchvertex3f_vertexbuffer = NULL;
8491 rsurface.batchvertex3f_bufferoffset = 0;
8492 rsurface.batchsvector3f = NULL;
8493 rsurface.batchsvector3f_vertexbuffer = NULL;
8494 rsurface.batchsvector3f_bufferoffset = 0;
8495 rsurface.batchtvector3f = NULL;
8496 rsurface.batchtvector3f_vertexbuffer = NULL;
8497 rsurface.batchtvector3f_bufferoffset = 0;
8498 rsurface.batchnormal3f = NULL;
8499 rsurface.batchnormal3f_vertexbuffer = NULL;
8500 rsurface.batchnormal3f_bufferoffset = 0;
8501 rsurface.batchlightmapcolor4f = NULL;
8502 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8503 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8504 rsurface.batchtexcoordtexture2f = NULL;
8505 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8506 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8507 rsurface.batchtexcoordlightmap2f = NULL;
8508 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8509 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8510 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8511 rsurface.batchelement3i_indexbuffer = NULL;
8512 rsurface.batchelement3i_bufferoffset = 0;
8513 rsurface.batchelement3s = NULL;
8514 rsurface.batchelement3s_indexbuffer = NULL;
8515 rsurface.batchelement3s_bufferoffset = 0;
8516 // we'll only be setting up certain arrays as needed
8517 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8518 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8519 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8520 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8521 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8522 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8523 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8525 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8526 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8528 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8529 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8530 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8531 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8532 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8533 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8536 for (i = 0;i < texturenumsurfaces;i++)
8538 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8539 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8540 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8541 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8542 // copy only the data requested
8543 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8544 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8545 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8547 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8548 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8549 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8550 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8551 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8553 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8554 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8556 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8557 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8558 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8559 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8560 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8561 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8563 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8564 numvertices += surfacenumvertices;
8565 numtriangles += surfacenumtriangles;
8568 // generate a 16bit index array as well if possible
8569 // (in general, dynamic batches fit)
8570 if (numvertices <= 65536)
8572 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8573 for (i = 0;i < numtriangles*3;i++)
8574 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8577 // since we've copied everything, the batch now starts at 0
8578 rsurface.batchfirstvertex = 0;
8579 rsurface.batchnumvertices = batchnumvertices;
8580 rsurface.batchfirsttriangle = 0;
8581 rsurface.batchnumtriangles = batchnumtriangles;
8584 // q1bsp surfaces rendered in vertex color mode have to have colors
8585 // calculated based on lightstyles
8586 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8588 // generate color arrays for the surfaces in this list
8593 const unsigned char *lm;
8594 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8595 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8596 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8598 for (i = 0;i < texturenumsurfaces;i++)
8600 surface = texturesurfacelist[i];
8601 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8602 surfacenumvertices = surface->num_vertices;
8603 if (surface->lightmapinfo->samples)
8605 for (j = 0;j < surfacenumvertices;j++)
8607 lm = surface->lightmapinfo->samples + offsets[j];
8608 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8609 VectorScale(lm, scale, c);
8610 if (surface->lightmapinfo->styles[1] != 255)
8612 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8614 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8615 VectorMA(c, scale, lm, c);
8616 if (surface->lightmapinfo->styles[2] != 255)
8619 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8620 VectorMA(c, scale, lm, c);
8621 if (surface->lightmapinfo->styles[3] != 255)
8624 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8625 VectorMA(c, scale, lm, c);
8632 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);
8638 for (j = 0;j < surfacenumvertices;j++)
8640 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8647 // if vertices are deformed (sprite flares and things in maps, possibly
8648 // water waves, bulges and other deformations), modify the copied vertices
8650 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8652 switch (deform->deform)
8655 case Q3DEFORM_PROJECTIONSHADOW:
8656 case Q3DEFORM_TEXT0:
8657 case Q3DEFORM_TEXT1:
8658 case Q3DEFORM_TEXT2:
8659 case Q3DEFORM_TEXT3:
8660 case Q3DEFORM_TEXT4:
8661 case Q3DEFORM_TEXT5:
8662 case Q3DEFORM_TEXT6:
8663 case Q3DEFORM_TEXT7:
8666 case Q3DEFORM_AUTOSPRITE:
8667 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8668 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8669 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8670 VectorNormalize(newforward);
8671 VectorNormalize(newright);
8672 VectorNormalize(newup);
8673 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8674 // rsurface.batchvertex3f_vertexbuffer = NULL;
8675 // rsurface.batchvertex3f_bufferoffset = 0;
8676 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8677 // rsurface.batchsvector3f_vertexbuffer = NULL;
8678 // rsurface.batchsvector3f_bufferoffset = 0;
8679 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8680 // rsurface.batchtvector3f_vertexbuffer = NULL;
8681 // rsurface.batchtvector3f_bufferoffset = 0;
8682 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8683 // rsurface.batchnormal3f_vertexbuffer = NULL;
8684 // rsurface.batchnormal3f_bufferoffset = 0;
8685 // a single autosprite surface can contain multiple sprites...
8686 for (j = 0;j < batchnumvertices - 3;j += 4)
8688 VectorClear(center);
8689 for (i = 0;i < 4;i++)
8690 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8691 VectorScale(center, 0.25f, center);
8692 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8693 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8694 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8695 for (i = 0;i < 4;i++)
8697 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8698 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8701 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8702 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8703 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);
8705 case Q3DEFORM_AUTOSPRITE2:
8706 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8707 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8708 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8709 VectorNormalize(newforward);
8710 VectorNormalize(newright);
8711 VectorNormalize(newup);
8712 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8713 // rsurface.batchvertex3f_vertexbuffer = NULL;
8714 // rsurface.batchvertex3f_bufferoffset = 0;
8716 const float *v1, *v2;
8726 memset(shortest, 0, sizeof(shortest));
8727 // a single autosprite surface can contain multiple sprites...
8728 for (j = 0;j < batchnumvertices - 3;j += 4)
8730 VectorClear(center);
8731 for (i = 0;i < 4;i++)
8732 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8733 VectorScale(center, 0.25f, center);
8734 // find the two shortest edges, then use them to define the
8735 // axis vectors for rotating around the central axis
8736 for (i = 0;i < 6;i++)
8738 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8739 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8740 l = VectorDistance2(v1, v2);
8741 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8743 l += (1.0f / 1024.0f);
8744 if (shortest[0].length2 > l || i == 0)
8746 shortest[1] = shortest[0];
8747 shortest[0].length2 = l;
8748 shortest[0].v1 = v1;
8749 shortest[0].v2 = v2;
8751 else if (shortest[1].length2 > l || i == 1)
8753 shortest[1].length2 = l;
8754 shortest[1].v1 = v1;
8755 shortest[1].v2 = v2;
8758 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8759 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8760 // this calculates the right vector from the shortest edge
8761 // and the up vector from the edge midpoints
8762 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8763 VectorNormalize(right);
8764 VectorSubtract(end, start, up);
8765 VectorNormalize(up);
8766 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8767 VectorSubtract(rsurface.localvieworigin, center, forward);
8768 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8769 VectorNegate(forward, forward);
8770 VectorReflect(forward, 0, up, forward);
8771 VectorNormalize(forward);
8772 CrossProduct(up, forward, newright);
8773 VectorNormalize(newright);
8774 // rotate the quad around the up axis vector, this is made
8775 // especially easy by the fact we know the quad is flat,
8776 // so we only have to subtract the center position and
8777 // measure distance along the right vector, and then
8778 // multiply that by the newright vector and add back the
8780 // we also need to subtract the old position to undo the
8781 // displacement from the center, which we do with a
8782 // DotProduct, the subtraction/addition of center is also
8783 // optimized into DotProducts here
8784 l = DotProduct(right, center);
8785 for (i = 0;i < 4;i++)
8787 v1 = rsurface.batchvertex3f + 3*(j+i);
8788 f = DotProduct(right, v1) - l;
8789 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8793 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8795 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8796 // rsurface.batchnormal3f_vertexbuffer = NULL;
8797 // rsurface.batchnormal3f_bufferoffset = 0;
8798 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8800 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8802 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8803 // rsurface.batchsvector3f_vertexbuffer = NULL;
8804 // rsurface.batchsvector3f_bufferoffset = 0;
8805 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8806 // rsurface.batchtvector3f_vertexbuffer = NULL;
8807 // rsurface.batchtvector3f_bufferoffset = 0;
8808 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);
8811 case Q3DEFORM_NORMAL:
8812 // deform the normals to make reflections wavey
8813 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8814 rsurface.batchnormal3f_vertexbuffer = NULL;
8815 rsurface.batchnormal3f_bufferoffset = 0;
8816 for (j = 0;j < batchnumvertices;j++)
8819 float *normal = rsurface.batchnormal3f + 3*j;
8820 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8821 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8822 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]);
8823 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]);
8824 VectorNormalize(normal);
8826 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8828 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8829 // rsurface.batchsvector3f_vertexbuffer = NULL;
8830 // rsurface.batchsvector3f_bufferoffset = 0;
8831 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8832 // rsurface.batchtvector3f_vertexbuffer = NULL;
8833 // rsurface.batchtvector3f_bufferoffset = 0;
8834 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);
8838 // deform vertex array to make wavey water and flags and such
8839 waveparms[0] = deform->waveparms[0];
8840 waveparms[1] = deform->waveparms[1];
8841 waveparms[2] = deform->waveparms[2];
8842 waveparms[3] = deform->waveparms[3];
8843 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8844 break; // if wavefunc is a nop, don't make a dynamic vertex array
8845 // this is how a divisor of vertex influence on deformation
8846 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8847 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8848 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8849 // rsurface.batchvertex3f_vertexbuffer = NULL;
8850 // rsurface.batchvertex3f_bufferoffset = 0;
8851 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8852 // rsurface.batchnormal3f_vertexbuffer = NULL;
8853 // rsurface.batchnormal3f_bufferoffset = 0;
8854 for (j = 0;j < batchnumvertices;j++)
8856 // if the wavefunc depends on time, evaluate it per-vertex
8859 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8860 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8862 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8864 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8865 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8866 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8868 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8869 // rsurface.batchsvector3f_vertexbuffer = NULL;
8870 // rsurface.batchsvector3f_bufferoffset = 0;
8871 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8872 // rsurface.batchtvector3f_vertexbuffer = NULL;
8873 // rsurface.batchtvector3f_bufferoffset = 0;
8874 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);
8877 case Q3DEFORM_BULGE:
8878 // deform vertex array to make the surface have moving bulges
8879 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8880 // rsurface.batchvertex3f_vertexbuffer = NULL;
8881 // rsurface.batchvertex3f_bufferoffset = 0;
8882 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8883 // rsurface.batchnormal3f_vertexbuffer = NULL;
8884 // rsurface.batchnormal3f_bufferoffset = 0;
8885 for (j = 0;j < batchnumvertices;j++)
8887 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8888 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8890 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8891 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8892 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8894 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8895 // rsurface.batchsvector3f_vertexbuffer = NULL;
8896 // rsurface.batchsvector3f_bufferoffset = 0;
8897 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8898 // rsurface.batchtvector3f_vertexbuffer = NULL;
8899 // rsurface.batchtvector3f_bufferoffset = 0;
8900 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);
8904 // deform vertex array
8905 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8906 break; // if wavefunc is a nop, don't make a dynamic vertex array
8907 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8908 VectorScale(deform->parms, scale, waveparms);
8909 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8910 // rsurface.batchvertex3f_vertexbuffer = NULL;
8911 // rsurface.batchvertex3f_bufferoffset = 0;
8912 for (j = 0;j < batchnumvertices;j++)
8913 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8918 // generate texcoords based on the chosen texcoord source
8919 switch(rsurface.texture->tcgen.tcgen)
8922 case Q3TCGEN_TEXTURE:
8924 case Q3TCGEN_LIGHTMAP:
8925 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8926 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8927 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8928 if (rsurface.batchtexcoordlightmap2f)
8929 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8931 case Q3TCGEN_VECTOR:
8932 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8933 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8934 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8935 for (j = 0;j < batchnumvertices;j++)
8937 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8938 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8941 case Q3TCGEN_ENVIRONMENT:
8942 // make environment reflections using a spheremap
8943 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8944 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8945 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8946 for (j = 0;j < batchnumvertices;j++)
8948 // identical to Q3A's method, but executed in worldspace so
8949 // carried models can be shiny too
8951 float viewer[3], d, reflected[3], worldreflected[3];
8953 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8954 // VectorNormalize(viewer);
8956 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8958 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8959 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8960 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8961 // note: this is proportinal to viewer, so we can normalize later
8963 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8964 VectorNormalize(worldreflected);
8966 // note: this sphere map only uses world x and z!
8967 // so positive and negative y will LOOK THE SAME.
8968 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8969 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8973 // the only tcmod that needs software vertex processing is turbulent, so
8974 // check for it here and apply the changes if needed
8975 // and we only support that as the first one
8976 // (handling a mixture of turbulent and other tcmods would be problematic
8977 // without punting it entirely to a software path)
8978 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8980 amplitude = rsurface.texture->tcmods[0].parms[1];
8981 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8982 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8983 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8984 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8985 for (j = 0;j < batchnumvertices;j++)
8987 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);
8988 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8992 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8994 // convert the modified arrays to vertex structs
8995 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8996 // rsurface.batchvertexmeshbuffer = NULL;
8997 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8998 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8999 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9000 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9001 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9002 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9003 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9005 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9007 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9008 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9011 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9012 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9013 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9014 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9015 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9016 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9017 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9018 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9019 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9023 void RSurf_DrawBatch(void)
9025 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9026 // through the pipeline, killing it earlier in the pipeline would have
9027 // per-surface overhead rather than per-batch overhead, so it's best to
9028 // reject it here, before it hits glDraw.
9029 if (rsurface.batchnumtriangles == 0)
9032 // batch debugging code
9033 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9039 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9040 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9043 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9045 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9047 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9048 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);
9055 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);
9058 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9060 // pick the closest matching water plane
9061 int planeindex, vertexindex, bestplaneindex = -1;
9065 r_waterstate_waterplane_t *p;
9066 qboolean prepared = false;
9068 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9070 if(p->camera_entity != rsurface.texture->camera_entity)
9075 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9077 if(rsurface.batchnumvertices == 0)
9080 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9082 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9083 d += fabs(PlaneDiff(vert, &p->plane));
9085 if (bestd > d || bestplaneindex < 0)
9088 bestplaneindex = planeindex;
9091 return bestplaneindex;
9092 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9093 // this situation though, as it might be better to render single larger
9094 // batches with useless stuff (backface culled for example) than to
9095 // render multiple smaller batches
9098 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9101 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9102 rsurface.passcolor4f_vertexbuffer = 0;
9103 rsurface.passcolor4f_bufferoffset = 0;
9104 for (i = 0;i < rsurface.batchnumvertices;i++)
9105 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9108 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9115 if (rsurface.passcolor4f)
9117 // generate color arrays
9118 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9119 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9120 rsurface.passcolor4f_vertexbuffer = 0;
9121 rsurface.passcolor4f_bufferoffset = 0;
9122 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)
9124 f = RSurf_FogVertex(v);
9133 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9134 rsurface.passcolor4f_vertexbuffer = 0;
9135 rsurface.passcolor4f_bufferoffset = 0;
9136 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9138 f = RSurf_FogVertex(v);
9147 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9154 if (!rsurface.passcolor4f)
9156 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9157 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9158 rsurface.passcolor4f_vertexbuffer = 0;
9159 rsurface.passcolor4f_bufferoffset = 0;
9160 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)
9162 f = RSurf_FogVertex(v);
9163 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9164 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9165 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9170 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9175 if (!rsurface.passcolor4f)
9177 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9178 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9179 rsurface.passcolor4f_vertexbuffer = 0;
9180 rsurface.passcolor4f_bufferoffset = 0;
9181 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9190 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9195 if (!rsurface.passcolor4f)
9197 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9198 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9199 rsurface.passcolor4f_vertexbuffer = 0;
9200 rsurface.passcolor4f_bufferoffset = 0;
9201 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9203 c2[0] = c[0] + r_refdef.scene.ambient;
9204 c2[1] = c[1] + r_refdef.scene.ambient;
9205 c2[2] = c[2] + r_refdef.scene.ambient;
9210 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9213 rsurface.passcolor4f = NULL;
9214 rsurface.passcolor4f_vertexbuffer = 0;
9215 rsurface.passcolor4f_bufferoffset = 0;
9216 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9217 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9218 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9219 GL_Color(r, g, b, a);
9220 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9224 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9226 // TODO: optimize applyfog && applycolor case
9227 // just apply fog if necessary, and tint the fog color array if necessary
9228 rsurface.passcolor4f = NULL;
9229 rsurface.passcolor4f_vertexbuffer = 0;
9230 rsurface.passcolor4f_bufferoffset = 0;
9231 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9232 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9233 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9234 GL_Color(r, g, b, a);
9238 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9241 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9242 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9243 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9244 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9245 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9246 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9247 GL_Color(r, g, b, a);
9251 static void RSurf_DrawBatch_GL11_ClampColor(void)
9256 if (!rsurface.passcolor4f)
9258 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9260 c2[0] = bound(0.0f, c1[0], 1.0f);
9261 c2[1] = bound(0.0f, c1[1], 1.0f);
9262 c2[2] = bound(0.0f, c1[2], 1.0f);
9263 c2[3] = bound(0.0f, c1[3], 1.0f);
9267 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9277 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9278 rsurface.passcolor4f_vertexbuffer = 0;
9279 rsurface.passcolor4f_bufferoffset = 0;
9280 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)
9282 f = -DotProduct(r_refdef.view.forward, n);
9284 f = f * 0.85 + 0.15; // work around so stuff won't get black
9285 f *= r_refdef.lightmapintensity;
9286 Vector4Set(c, f, f, f, 1);
9290 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9292 RSurf_DrawBatch_GL11_ApplyFakeLight();
9293 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9294 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9295 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9296 GL_Color(r, g, b, a);
9300 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9308 vec3_t ambientcolor;
9309 vec3_t diffusecolor;
9313 VectorCopy(rsurface.modellight_lightdir, lightdir);
9314 f = 0.5f * r_refdef.lightmapintensity;
9315 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9316 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9317 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9318 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9319 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9320 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9322 if (VectorLength2(diffusecolor) > 0)
9324 // q3-style directional shading
9325 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9326 rsurface.passcolor4f_vertexbuffer = 0;
9327 rsurface.passcolor4f_bufferoffset = 0;
9328 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)
9330 if ((f = DotProduct(n, lightdir)) > 0)
9331 VectorMA(ambientcolor, f, diffusecolor, c);
9333 VectorCopy(ambientcolor, c);
9340 *applycolor = false;
9344 *r = ambientcolor[0];
9345 *g = ambientcolor[1];
9346 *b = ambientcolor[2];
9347 rsurface.passcolor4f = NULL;
9348 rsurface.passcolor4f_vertexbuffer = 0;
9349 rsurface.passcolor4f_bufferoffset = 0;
9353 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9355 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9356 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9357 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9358 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9359 GL_Color(r, g, b, a);
9363 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9371 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9372 rsurface.passcolor4f_vertexbuffer = 0;
9373 rsurface.passcolor4f_bufferoffset = 0;
9375 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9377 f = 1 - RSurf_FogVertex(v);
9385 void RSurf_SetupDepthAndCulling(void)
9387 // submodels are biased to avoid z-fighting with world surfaces that they
9388 // may be exactly overlapping (avoids z-fighting artifacts on certain
9389 // doors and things in Quake maps)
9390 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9391 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9392 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9393 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9396 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9398 // transparent sky would be ridiculous
9399 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9401 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9402 skyrenderlater = true;
9403 RSurf_SetupDepthAndCulling();
9405 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9406 // skymasking on them, and Quake3 never did sky masking (unlike
9407 // software Quake and software Quake2), so disable the sky masking
9408 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9409 // and skymasking also looks very bad when noclipping outside the
9410 // level, so don't use it then either.
9411 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9413 R_Mesh_ResetTextureState();
9414 if (skyrendermasked)
9416 R_SetupShader_DepthOrShadow();
9417 // depth-only (masking)
9418 GL_ColorMask(0,0,0,0);
9419 // just to make sure that braindead drivers don't draw
9420 // anything despite that colormask...
9421 GL_BlendFunc(GL_ZERO, GL_ONE);
9422 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9423 if (rsurface.batchvertex3fbuffer)
9424 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9426 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9430 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9432 GL_BlendFunc(GL_ONE, GL_ZERO);
9433 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9434 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9435 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9438 if (skyrendermasked)
9439 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9441 R_Mesh_ResetTextureState();
9442 GL_Color(1, 1, 1, 1);
9445 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9446 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9447 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9449 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9453 // render screenspace normalmap to texture
9455 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9460 // bind lightmap texture
9462 // water/refraction/reflection/camera surfaces have to be handled specially
9463 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9465 int start, end, startplaneindex;
9466 for (start = 0;start < texturenumsurfaces;start = end)
9468 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9469 if(startplaneindex < 0)
9471 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9472 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9476 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9478 // now that we have a batch using the same planeindex, render it
9479 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9481 // render water or distortion background
9483 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));
9485 // blend surface on top
9486 GL_DepthMask(false);
9487 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9490 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9492 // render surface with reflection texture as input
9493 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9494 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));
9501 // render surface batch normally
9502 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9503 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9507 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9509 // OpenGL 1.3 path - anything not completely ancient
9510 qboolean applycolor;
9513 const texturelayer_t *layer;
9514 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);
9515 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9517 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9520 int layertexrgbscale;
9521 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9523 if (layerindex == 0)
9527 GL_AlphaTest(false);
9528 GL_DepthFunc(GL_EQUAL);
9531 GL_DepthMask(layer->depthmask && writedepth);
9532 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9533 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9535 layertexrgbscale = 4;
9536 VectorScale(layer->color, 0.25f, layercolor);
9538 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9540 layertexrgbscale = 2;
9541 VectorScale(layer->color, 0.5f, layercolor);
9545 layertexrgbscale = 1;
9546 VectorScale(layer->color, 1.0f, layercolor);
9548 layercolor[3] = layer->color[3];
9549 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9550 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9551 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9552 switch (layer->type)
9554 case TEXTURELAYERTYPE_LITTEXTURE:
9555 // single-pass lightmapped texture with 2x rgbscale
9556 R_Mesh_TexBind(0, r_texture_white);
9557 R_Mesh_TexMatrix(0, NULL);
9558 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9559 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9560 R_Mesh_TexBind(1, layer->texture);
9561 R_Mesh_TexMatrix(1, &layer->texmatrix);
9562 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9563 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9564 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9565 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9566 else if (FAKELIGHT_ENABLED)
9567 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9568 else if (rsurface.uselightmaptexture)
9569 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9571 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9573 case TEXTURELAYERTYPE_TEXTURE:
9574 // singletexture unlit texture with transparency support
9575 R_Mesh_TexBind(0, layer->texture);
9576 R_Mesh_TexMatrix(0, &layer->texmatrix);
9577 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9578 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9579 R_Mesh_TexBind(1, 0);
9580 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9581 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9583 case TEXTURELAYERTYPE_FOG:
9584 // singletexture fogging
9587 R_Mesh_TexBind(0, layer->texture);
9588 R_Mesh_TexMatrix(0, &layer->texmatrix);
9589 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9590 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9594 R_Mesh_TexBind(0, 0);
9595 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9597 R_Mesh_TexBind(1, 0);
9598 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9599 // generate a color array for the fog pass
9600 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9601 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9605 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9608 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9610 GL_DepthFunc(GL_LEQUAL);
9611 GL_AlphaTest(false);
9615 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9617 // OpenGL 1.1 - crusty old voodoo path
9620 const texturelayer_t *layer;
9621 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);
9622 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9624 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9626 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9628 if (layerindex == 0)
9632 GL_AlphaTest(false);
9633 GL_DepthFunc(GL_EQUAL);
9636 GL_DepthMask(layer->depthmask && writedepth);
9637 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9638 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9639 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9640 switch (layer->type)
9642 case TEXTURELAYERTYPE_LITTEXTURE:
9643 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9645 // two-pass lit texture with 2x rgbscale
9646 // first the lightmap pass
9647 R_Mesh_TexBind(0, r_texture_white);
9648 R_Mesh_TexMatrix(0, NULL);
9649 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9650 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9651 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9652 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9653 else if (FAKELIGHT_ENABLED)
9654 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9655 else if (rsurface.uselightmaptexture)
9656 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9658 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9659 // then apply the texture to it
9660 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9661 R_Mesh_TexBind(0, layer->texture);
9662 R_Mesh_TexMatrix(0, &layer->texmatrix);
9663 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9664 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9665 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);
9669 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9670 R_Mesh_TexBind(0, layer->texture);
9671 R_Mesh_TexMatrix(0, &layer->texmatrix);
9672 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9673 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9674 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9675 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);
9677 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);
9680 case TEXTURELAYERTYPE_TEXTURE:
9681 // singletexture unlit texture with transparency support
9682 R_Mesh_TexBind(0, layer->texture);
9683 R_Mesh_TexMatrix(0, &layer->texmatrix);
9684 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9685 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9686 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);
9688 case TEXTURELAYERTYPE_FOG:
9689 // singletexture fogging
9692 R_Mesh_TexBind(0, layer->texture);
9693 R_Mesh_TexMatrix(0, &layer->texmatrix);
9694 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9695 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9699 R_Mesh_TexBind(0, 0);
9700 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9702 // generate a color array for the fog pass
9703 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9704 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9708 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9711 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9713 GL_DepthFunc(GL_LEQUAL);
9714 GL_AlphaTest(false);
9718 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9722 r_vertexgeneric_t *batchvertex;
9725 // R_Mesh_ResetTextureState();
9726 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9728 if(rsurface.texture && rsurface.texture->currentskinframe)
9730 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9731 c[3] *= rsurface.texture->currentalpha;
9741 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9743 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9744 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9745 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9748 // brighten it up (as texture value 127 means "unlit")
9749 c[0] *= 2 * r_refdef.view.colorscale;
9750 c[1] *= 2 * r_refdef.view.colorscale;
9751 c[2] *= 2 * r_refdef.view.colorscale;
9753 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9754 c[3] *= r_wateralpha.value;
9756 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9758 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9759 GL_DepthMask(false);
9761 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9763 GL_BlendFunc(GL_ONE, GL_ONE);
9764 GL_DepthMask(false);
9766 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9768 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9769 GL_DepthMask(false);
9771 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9773 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9774 GL_DepthMask(false);
9778 GL_BlendFunc(GL_ONE, GL_ZERO);
9779 GL_DepthMask(writedepth);
9782 if (r_showsurfaces.integer == 3)
9784 rsurface.passcolor4f = NULL;
9786 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9788 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9790 rsurface.passcolor4f = NULL;
9791 rsurface.passcolor4f_vertexbuffer = 0;
9792 rsurface.passcolor4f_bufferoffset = 0;
9794 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9796 qboolean applycolor = true;
9799 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9801 r_refdef.lightmapintensity = 1;
9802 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9803 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9805 else if (FAKELIGHT_ENABLED)
9807 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9809 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9810 RSurf_DrawBatch_GL11_ApplyFakeLight();
9811 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9815 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9817 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9818 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9819 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9822 if(!rsurface.passcolor4f)
9823 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9825 RSurf_DrawBatch_GL11_ApplyAmbient();
9826 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9827 if(r_refdef.fogenabled)
9828 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9829 RSurf_DrawBatch_GL11_ClampColor();
9831 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9832 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9835 else if (!r_refdef.view.showdebug)
9837 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9838 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9839 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9841 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9842 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9844 R_Mesh_PrepareVertices_Generic_Unlock();
9847 else if (r_showsurfaces.integer == 4)
9849 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9850 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9851 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9853 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9854 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9855 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9857 R_Mesh_PrepareVertices_Generic_Unlock();
9860 else if (r_showsurfaces.integer == 2)
9863 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9864 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9865 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9867 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9868 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9869 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9870 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9871 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9872 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9873 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9875 R_Mesh_PrepareVertices_Generic_Unlock();
9876 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9880 int texturesurfaceindex;
9882 const msurface_t *surface;
9883 float surfacecolor4f[4];
9884 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9885 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9887 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9889 surface = texturesurfacelist[texturesurfaceindex];
9890 k = (int)(((size_t)surface) / sizeof(msurface_t));
9891 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9892 for (j = 0;j < surface->num_vertices;j++)
9894 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9895 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9899 R_Mesh_PrepareVertices_Generic_Unlock();
9904 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9907 RSurf_SetupDepthAndCulling();
9908 if (r_showsurfaces.integer)
9910 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9913 switch (vid.renderpath)
9915 case RENDERPATH_GL20:
9916 case RENDERPATH_D3D9:
9917 case RENDERPATH_D3D10:
9918 case RENDERPATH_D3D11:
9919 case RENDERPATH_SOFT:
9920 case RENDERPATH_GLES2:
9921 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9923 case RENDERPATH_GL13:
9924 case RENDERPATH_GLES1:
9925 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9927 case RENDERPATH_GL11:
9928 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9934 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9937 RSurf_SetupDepthAndCulling();
9938 if (r_showsurfaces.integer)
9940 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9943 switch (vid.renderpath)
9945 case RENDERPATH_GL20:
9946 case RENDERPATH_D3D9:
9947 case RENDERPATH_D3D10:
9948 case RENDERPATH_D3D11:
9949 case RENDERPATH_SOFT:
9950 case RENDERPATH_GLES2:
9951 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9953 case RENDERPATH_GL13:
9954 case RENDERPATH_GLES1:
9955 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9957 case RENDERPATH_GL11:
9958 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9964 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9967 int texturenumsurfaces, endsurface;
9969 const msurface_t *surface;
9970 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9972 // if the model is static it doesn't matter what value we give for
9973 // wantnormals and wanttangents, so this logic uses only rules applicable
9974 // to a model, knowing that they are meaningless otherwise
9975 if (ent == r_refdef.scene.worldentity)
9976 RSurf_ActiveWorldEntity();
9977 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9978 RSurf_ActiveModelEntity(ent, false, false, false);
9981 switch (vid.renderpath)
9983 case RENDERPATH_GL20:
9984 case RENDERPATH_D3D9:
9985 case RENDERPATH_D3D10:
9986 case RENDERPATH_D3D11:
9987 case RENDERPATH_SOFT:
9988 case RENDERPATH_GLES2:
9989 RSurf_ActiveModelEntity(ent, true, true, false);
9991 case RENDERPATH_GL11:
9992 case RENDERPATH_GL13:
9993 case RENDERPATH_GLES1:
9994 RSurf_ActiveModelEntity(ent, true, false, false);
9999 if (r_transparentdepthmasking.integer)
10001 qboolean setup = false;
10002 for (i = 0;i < numsurfaces;i = j)
10005 surface = rsurface.modelsurfaces + surfacelist[i];
10006 texture = surface->texture;
10007 rsurface.texture = R_GetCurrentTexture(texture);
10008 rsurface.lightmaptexture = NULL;
10009 rsurface.deluxemaptexture = NULL;
10010 rsurface.uselightmaptexture = false;
10011 // scan ahead until we find a different texture
10012 endsurface = min(i + 1024, numsurfaces);
10013 texturenumsurfaces = 0;
10014 texturesurfacelist[texturenumsurfaces++] = surface;
10015 for (;j < endsurface;j++)
10017 surface = rsurface.modelsurfaces + surfacelist[j];
10018 if (texture != surface->texture)
10020 texturesurfacelist[texturenumsurfaces++] = surface;
10022 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10024 // render the range of surfaces as depth
10028 GL_ColorMask(0,0,0,0);
10030 GL_DepthTest(true);
10031 GL_BlendFunc(GL_ONE, GL_ZERO);
10032 GL_DepthMask(true);
10033 // R_Mesh_ResetTextureState();
10034 R_SetupShader_DepthOrShadow();
10036 RSurf_SetupDepthAndCulling();
10037 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10038 if (rsurface.batchvertex3fbuffer)
10039 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10041 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10045 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10048 for (i = 0;i < numsurfaces;i = j)
10051 surface = rsurface.modelsurfaces + surfacelist[i];
10052 texture = surface->texture;
10053 rsurface.texture = R_GetCurrentTexture(texture);
10054 // scan ahead until we find a different texture
10055 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10056 texturenumsurfaces = 0;
10057 texturesurfacelist[texturenumsurfaces++] = surface;
10058 if(FAKELIGHT_ENABLED)
10060 rsurface.lightmaptexture = NULL;
10061 rsurface.deluxemaptexture = NULL;
10062 rsurface.uselightmaptexture = false;
10063 for (;j < endsurface;j++)
10065 surface = rsurface.modelsurfaces + surfacelist[j];
10066 if (texture != surface->texture)
10068 texturesurfacelist[texturenumsurfaces++] = surface;
10073 rsurface.lightmaptexture = surface->lightmaptexture;
10074 rsurface.deluxemaptexture = surface->deluxemaptexture;
10075 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10076 for (;j < endsurface;j++)
10078 surface = rsurface.modelsurfaces + surfacelist[j];
10079 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10081 texturesurfacelist[texturenumsurfaces++] = surface;
10084 // render the range of surfaces
10085 if (ent == r_refdef.scene.worldentity)
10086 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10088 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10090 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10093 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10095 // transparent surfaces get pushed off into the transparent queue
10096 int surfacelistindex;
10097 const msurface_t *surface;
10098 vec3_t tempcenter, center;
10099 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10101 surface = texturesurfacelist[surfacelistindex];
10102 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10103 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10104 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10105 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10106 if (queueentity->transparent_offset) // transparent offset
10108 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10109 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10110 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10112 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10116 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10118 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10120 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10122 RSurf_SetupDepthAndCulling();
10123 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10124 if (rsurface.batchvertex3fbuffer)
10125 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10127 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10131 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10133 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10136 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10139 if (!rsurface.texture->currentnumlayers)
10141 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10142 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10144 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10146 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10147 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10148 else if (!rsurface.texture->currentnumlayers)
10150 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10152 // in the deferred case, transparent surfaces were queued during prepass
10153 if (!r_shadow_usingdeferredprepass)
10154 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10158 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10159 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10164 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10167 texture_t *texture;
10168 R_FrameData_SetMark();
10169 // break the surface list down into batches by texture and use of lightmapping
10170 for (i = 0;i < numsurfaces;i = j)
10173 // texture is the base texture pointer, rsurface.texture is the
10174 // current frame/skin the texture is directing us to use (for example
10175 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10176 // use skin 1 instead)
10177 texture = surfacelist[i]->texture;
10178 rsurface.texture = R_GetCurrentTexture(texture);
10179 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10181 // if this texture is not the kind we want, skip ahead to the next one
10182 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10186 if(FAKELIGHT_ENABLED || depthonly || prepass)
10188 rsurface.lightmaptexture = NULL;
10189 rsurface.deluxemaptexture = NULL;
10190 rsurface.uselightmaptexture = false;
10191 // simply scan ahead until we find a different texture or lightmap state
10192 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10197 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10198 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10199 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10200 // simply scan ahead until we find a different texture or lightmap state
10201 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10204 // render the range of surfaces
10205 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10207 R_FrameData_ReturnToMark();
10210 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10214 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10217 if (!rsurface.texture->currentnumlayers)
10219 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10220 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10222 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10224 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10225 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10226 else if (!rsurface.texture->currentnumlayers)
10228 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10230 // in the deferred case, transparent surfaces were queued during prepass
10231 if (!r_shadow_usingdeferredprepass)
10232 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10236 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10237 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10242 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10245 texture_t *texture;
10246 R_FrameData_SetMark();
10247 // break the surface list down into batches by texture and use of lightmapping
10248 for (i = 0;i < numsurfaces;i = j)
10251 // texture is the base texture pointer, rsurface.texture is the
10252 // current frame/skin the texture is directing us to use (for example
10253 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10254 // use skin 1 instead)
10255 texture = surfacelist[i]->texture;
10256 rsurface.texture = R_GetCurrentTexture(texture);
10257 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10259 // if this texture is not the kind we want, skip ahead to the next one
10260 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10264 if(FAKELIGHT_ENABLED || depthonly || prepass)
10266 rsurface.lightmaptexture = NULL;
10267 rsurface.deluxemaptexture = NULL;
10268 rsurface.uselightmaptexture = false;
10269 // simply scan ahead until we find a different texture or lightmap state
10270 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10275 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10276 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10277 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10278 // simply scan ahead until we find a different texture or lightmap state
10279 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10282 // render the range of surfaces
10283 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10285 R_FrameData_ReturnToMark();
10288 float locboxvertex3f[6*4*3] =
10290 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10291 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10292 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10293 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10294 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10295 1,0,0, 0,0,0, 0,1,0, 1,1,0
10298 unsigned short locboxelements[6*2*3] =
10303 12,13,14, 12,14,15,
10304 16,17,18, 16,18,19,
10308 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10311 cl_locnode_t *loc = (cl_locnode_t *)ent;
10313 float vertex3f[6*4*3];
10315 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10316 GL_DepthMask(false);
10317 GL_DepthRange(0, 1);
10318 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10319 GL_DepthTest(true);
10320 GL_CullFace(GL_NONE);
10321 R_EntityMatrix(&identitymatrix);
10323 // R_Mesh_ResetTextureState();
10325 i = surfacelist[0];
10326 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10327 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10328 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10329 surfacelist[0] < 0 ? 0.5f : 0.125f);
10331 if (VectorCompare(loc->mins, loc->maxs))
10333 VectorSet(size, 2, 2, 2);
10334 VectorMA(loc->mins, -0.5f, size, mins);
10338 VectorCopy(loc->mins, mins);
10339 VectorSubtract(loc->maxs, loc->mins, size);
10342 for (i = 0;i < 6*4*3;)
10343 for (j = 0;j < 3;j++, i++)
10344 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10346 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10347 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10348 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10351 void R_DrawLocs(void)
10354 cl_locnode_t *loc, *nearestloc;
10356 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10357 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10359 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10360 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10364 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10366 if (decalsystem->decals)
10367 Mem_Free(decalsystem->decals);
10368 memset(decalsystem, 0, sizeof(*decalsystem));
10371 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)
10374 tridecal_t *decals;
10377 // expand or initialize the system
10378 if (decalsystem->maxdecals <= decalsystem->numdecals)
10380 decalsystem_t old = *decalsystem;
10381 qboolean useshortelements;
10382 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10383 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10384 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)));
10385 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10386 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10387 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10388 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10389 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10390 if (decalsystem->numdecals)
10391 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10393 Mem_Free(old.decals);
10394 for (i = 0;i < decalsystem->maxdecals*3;i++)
10395 decalsystem->element3i[i] = i;
10396 if (useshortelements)
10397 for (i = 0;i < decalsystem->maxdecals*3;i++)
10398 decalsystem->element3s[i] = i;
10401 // grab a decal and search for another free slot for the next one
10402 decals = decalsystem->decals;
10403 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10404 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10406 decalsystem->freedecal = i;
10407 if (decalsystem->numdecals <= i)
10408 decalsystem->numdecals = i + 1;
10410 // initialize the decal
10412 decal->triangleindex = triangleindex;
10413 decal->surfaceindex = surfaceindex;
10414 decal->decalsequence = decalsequence;
10415 decal->color4f[0][0] = c0[0];
10416 decal->color4f[0][1] = c0[1];
10417 decal->color4f[0][2] = c0[2];
10418 decal->color4f[0][3] = 1;
10419 decal->color4f[1][0] = c1[0];
10420 decal->color4f[1][1] = c1[1];
10421 decal->color4f[1][2] = c1[2];
10422 decal->color4f[1][3] = 1;
10423 decal->color4f[2][0] = c2[0];
10424 decal->color4f[2][1] = c2[1];
10425 decal->color4f[2][2] = c2[2];
10426 decal->color4f[2][3] = 1;
10427 decal->vertex3f[0][0] = v0[0];
10428 decal->vertex3f[0][1] = v0[1];
10429 decal->vertex3f[0][2] = v0[2];
10430 decal->vertex3f[1][0] = v1[0];
10431 decal->vertex3f[1][1] = v1[1];
10432 decal->vertex3f[1][2] = v1[2];
10433 decal->vertex3f[2][0] = v2[0];
10434 decal->vertex3f[2][1] = v2[1];
10435 decal->vertex3f[2][2] = v2[2];
10436 decal->texcoord2f[0][0] = t0[0];
10437 decal->texcoord2f[0][1] = t0[1];
10438 decal->texcoord2f[1][0] = t1[0];
10439 decal->texcoord2f[1][1] = t1[1];
10440 decal->texcoord2f[2][0] = t2[0];
10441 decal->texcoord2f[2][1] = t2[1];
10442 TriangleNormal(v0, v1, v2, decal->plane);
10443 VectorNormalize(decal->plane);
10444 decal->plane[3] = DotProduct(v0, decal->plane);
10447 extern cvar_t cl_decals_bias;
10448 extern cvar_t cl_decals_models;
10449 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10450 // baseparms, parms, temps
10451 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)
10456 const float *vertex3f;
10457 const float *normal3f;
10459 float points[2][9][3];
10466 e = rsurface.modelelement3i + 3*triangleindex;
10468 vertex3f = rsurface.modelvertex3f;
10469 normal3f = rsurface.modelnormal3f;
10473 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10475 index = 3*e[cornerindex];
10476 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10481 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10483 index = 3*e[cornerindex];
10484 VectorCopy(vertex3f + index, v[cornerindex]);
10489 //TriangleNormal(v[0], v[1], v[2], normal);
10490 //if (DotProduct(normal, localnormal) < 0.0f)
10492 // clip by each of the box planes formed from the projection matrix
10493 // if anything survives, we emit the decal
10494 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]);
10497 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]);
10500 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]);
10503 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]);
10506 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]);
10509 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]);
10512 // some part of the triangle survived, so we have to accept it...
10515 // dynamic always uses the original triangle
10517 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10519 index = 3*e[cornerindex];
10520 VectorCopy(vertex3f + index, v[cornerindex]);
10523 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10525 // convert vertex positions to texcoords
10526 Matrix4x4_Transform(projection, v[cornerindex], temp);
10527 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10528 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10529 // calculate distance fade from the projection origin
10530 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10531 f = bound(0.0f, f, 1.0f);
10532 c[cornerindex][0] = r * f;
10533 c[cornerindex][1] = g * f;
10534 c[cornerindex][2] = b * f;
10535 c[cornerindex][3] = 1.0f;
10536 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10539 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);
10541 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10542 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);
10544 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)
10546 matrix4x4_t projection;
10547 decalsystem_t *decalsystem;
10550 const msurface_t *surface;
10551 const msurface_t *surfaces;
10552 const int *surfacelist;
10553 const texture_t *texture;
10555 int numsurfacelist;
10556 int surfacelistindex;
10559 float localorigin[3];
10560 float localnormal[3];
10561 float localmins[3];
10562 float localmaxs[3];
10565 float planes[6][4];
10568 int bih_triangles_count;
10569 int bih_triangles[256];
10570 int bih_surfaces[256];
10572 decalsystem = &ent->decalsystem;
10573 model = ent->model;
10574 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10576 R_DecalSystem_Reset(&ent->decalsystem);
10580 if (!model->brush.data_leafs && !cl_decals_models.integer)
10582 if (decalsystem->model)
10583 R_DecalSystem_Reset(decalsystem);
10587 if (decalsystem->model != model)
10588 R_DecalSystem_Reset(decalsystem);
10589 decalsystem->model = model;
10591 RSurf_ActiveModelEntity(ent, true, false, false);
10593 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10594 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10595 VectorNormalize(localnormal);
10596 localsize = worldsize*rsurface.inversematrixscale;
10597 localmins[0] = localorigin[0] - localsize;
10598 localmins[1] = localorigin[1] - localsize;
10599 localmins[2] = localorigin[2] - localsize;
10600 localmaxs[0] = localorigin[0] + localsize;
10601 localmaxs[1] = localorigin[1] + localsize;
10602 localmaxs[2] = localorigin[2] + localsize;
10604 //VectorCopy(localnormal, planes[4]);
10605 //VectorVectors(planes[4], planes[2], planes[0]);
10606 AnglesFromVectors(angles, localnormal, NULL, false);
10607 AngleVectors(angles, planes[0], planes[2], planes[4]);
10608 VectorNegate(planes[0], planes[1]);
10609 VectorNegate(planes[2], planes[3]);
10610 VectorNegate(planes[4], planes[5]);
10611 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10612 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10613 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10614 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10615 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10616 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10621 matrix4x4_t forwardprojection;
10622 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10623 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10628 float projectionvector[4][3];
10629 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10630 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10631 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10632 projectionvector[0][0] = planes[0][0] * ilocalsize;
10633 projectionvector[0][1] = planes[1][0] * ilocalsize;
10634 projectionvector[0][2] = planes[2][0] * ilocalsize;
10635 projectionvector[1][0] = planes[0][1] * ilocalsize;
10636 projectionvector[1][1] = planes[1][1] * ilocalsize;
10637 projectionvector[1][2] = planes[2][1] * ilocalsize;
10638 projectionvector[2][0] = planes[0][2] * ilocalsize;
10639 projectionvector[2][1] = planes[1][2] * ilocalsize;
10640 projectionvector[2][2] = planes[2][2] * ilocalsize;
10641 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10642 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10643 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10644 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10648 dynamic = model->surfmesh.isanimated;
10649 numsurfacelist = model->nummodelsurfaces;
10650 surfacelist = model->sortedmodelsurfaces;
10651 surfaces = model->data_surfaces;
10654 bih_triangles_count = -1;
10657 if(model->render_bih.numleafs)
10658 bih = &model->render_bih;
10659 else if(model->collision_bih.numleafs)
10660 bih = &model->collision_bih;
10663 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10664 if(bih_triangles_count == 0)
10666 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10668 if(bih_triangles_count > 0)
10670 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10672 surfaceindex = bih_surfaces[triangleindex];
10673 surface = surfaces + surfaceindex;
10674 texture = surface->texture;
10675 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10677 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10679 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10684 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10686 surfaceindex = surfacelist[surfacelistindex];
10687 surface = surfaces + surfaceindex;
10688 // check cull box first because it rejects more than any other check
10689 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10691 // skip transparent surfaces
10692 texture = surface->texture;
10693 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10695 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10697 numtriangles = surface->num_triangles;
10698 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10699 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10704 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10705 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)
10707 int renderentityindex;
10708 float worldmins[3];
10709 float worldmaxs[3];
10710 entity_render_t *ent;
10712 if (!cl_decals_newsystem.integer)
10715 worldmins[0] = worldorigin[0] - worldsize;
10716 worldmins[1] = worldorigin[1] - worldsize;
10717 worldmins[2] = worldorigin[2] - worldsize;
10718 worldmaxs[0] = worldorigin[0] + worldsize;
10719 worldmaxs[1] = worldorigin[1] + worldsize;
10720 worldmaxs[2] = worldorigin[2] + worldsize;
10722 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10724 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10726 ent = r_refdef.scene.entities[renderentityindex];
10727 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10730 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10734 typedef struct r_decalsystem_splatqueue_s
10736 vec3_t worldorigin;
10737 vec3_t worldnormal;
10743 r_decalsystem_splatqueue_t;
10745 int r_decalsystem_numqueued = 0;
10746 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10748 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)
10750 r_decalsystem_splatqueue_t *queue;
10752 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10755 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10756 VectorCopy(worldorigin, queue->worldorigin);
10757 VectorCopy(worldnormal, queue->worldnormal);
10758 Vector4Set(queue->color, r, g, b, a);
10759 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10760 queue->worldsize = worldsize;
10761 queue->decalsequence = cl.decalsequence++;
10764 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10767 r_decalsystem_splatqueue_t *queue;
10769 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10770 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);
10771 r_decalsystem_numqueued = 0;
10774 extern cvar_t cl_decals_max;
10775 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10778 decalsystem_t *decalsystem = &ent->decalsystem;
10785 if (!decalsystem->numdecals)
10788 if (r_showsurfaces.integer)
10791 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10793 R_DecalSystem_Reset(decalsystem);
10797 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10798 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10800 if (decalsystem->lastupdatetime)
10801 frametime = (cl.time - decalsystem->lastupdatetime);
10804 decalsystem->lastupdatetime = cl.time;
10805 decal = decalsystem->decals;
10806 numdecals = decalsystem->numdecals;
10808 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10810 if (decal->color4f[0][3])
10812 decal->lived += frametime;
10813 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10815 memset(decal, 0, sizeof(*decal));
10816 if (decalsystem->freedecal > i)
10817 decalsystem->freedecal = i;
10821 decal = decalsystem->decals;
10822 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10825 // collapse the array by shuffling the tail decals into the gaps
10828 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10829 decalsystem->freedecal++;
10830 if (decalsystem->freedecal == numdecals)
10832 decal[decalsystem->freedecal] = decal[--numdecals];
10835 decalsystem->numdecals = numdecals;
10837 if (numdecals <= 0)
10839 // if there are no decals left, reset decalsystem
10840 R_DecalSystem_Reset(decalsystem);
10844 extern skinframe_t *decalskinframe;
10845 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10848 decalsystem_t *decalsystem = &ent->decalsystem;
10857 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10860 numdecals = decalsystem->numdecals;
10864 if (r_showsurfaces.integer)
10867 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10869 R_DecalSystem_Reset(decalsystem);
10873 // if the model is static it doesn't matter what value we give for
10874 // wantnormals and wanttangents, so this logic uses only rules applicable
10875 // to a model, knowing that they are meaningless otherwise
10876 if (ent == r_refdef.scene.worldentity)
10877 RSurf_ActiveWorldEntity();
10879 RSurf_ActiveModelEntity(ent, false, false, false);
10881 decalsystem->lastupdatetime = cl.time;
10882 decal = decalsystem->decals;
10884 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10886 // update vertex positions for animated models
10887 v3f = decalsystem->vertex3f;
10888 c4f = decalsystem->color4f;
10889 t2f = decalsystem->texcoord2f;
10890 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10892 if (!decal->color4f[0][3])
10895 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10899 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10902 // update color values for fading decals
10903 if (decal->lived >= cl_decals_time.value)
10904 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10908 c4f[ 0] = decal->color4f[0][0] * alpha;
10909 c4f[ 1] = decal->color4f[0][1] * alpha;
10910 c4f[ 2] = decal->color4f[0][2] * alpha;
10912 c4f[ 4] = decal->color4f[1][0] * alpha;
10913 c4f[ 5] = decal->color4f[1][1] * alpha;
10914 c4f[ 6] = decal->color4f[1][2] * alpha;
10916 c4f[ 8] = decal->color4f[2][0] * alpha;
10917 c4f[ 9] = decal->color4f[2][1] * alpha;
10918 c4f[10] = decal->color4f[2][2] * alpha;
10921 t2f[0] = decal->texcoord2f[0][0];
10922 t2f[1] = decal->texcoord2f[0][1];
10923 t2f[2] = decal->texcoord2f[1][0];
10924 t2f[3] = decal->texcoord2f[1][1];
10925 t2f[4] = decal->texcoord2f[2][0];
10926 t2f[5] = decal->texcoord2f[2][1];
10928 // update vertex positions for animated models
10929 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10931 e = rsurface.modelelement3i + 3*decal->triangleindex;
10932 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10933 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10934 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10938 VectorCopy(decal->vertex3f[0], v3f);
10939 VectorCopy(decal->vertex3f[1], v3f + 3);
10940 VectorCopy(decal->vertex3f[2], v3f + 6);
10943 if (r_refdef.fogenabled)
10945 alpha = RSurf_FogVertex(v3f);
10946 VectorScale(c4f, alpha, c4f);
10947 alpha = RSurf_FogVertex(v3f + 3);
10948 VectorScale(c4f + 4, alpha, c4f + 4);
10949 alpha = RSurf_FogVertex(v3f + 6);
10950 VectorScale(c4f + 8, alpha, c4f + 8);
10961 r_refdef.stats.drawndecals += numtris;
10963 // now render the decals all at once
10964 // (this assumes they all use one particle font texture!)
10965 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);
10966 // R_Mesh_ResetTextureState();
10967 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10968 GL_DepthMask(false);
10969 GL_DepthRange(0, 1);
10970 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10971 GL_DepthTest(true);
10972 GL_CullFace(GL_NONE);
10973 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10974 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10975 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10979 static void R_DrawModelDecals(void)
10983 // fade faster when there are too many decals
10984 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10985 for (i = 0;i < r_refdef.scene.numentities;i++)
10986 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10988 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10989 for (i = 0;i < r_refdef.scene.numentities;i++)
10990 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10991 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10993 R_DecalSystem_ApplySplatEntitiesQueue();
10995 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10996 for (i = 0;i < r_refdef.scene.numentities;i++)
10997 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10999 r_refdef.stats.totaldecals += numdecals;
11001 if (r_showsurfaces.integer)
11004 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11006 for (i = 0;i < r_refdef.scene.numentities;i++)
11008 if (!r_refdef.viewcache.entityvisible[i])
11010 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11011 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11015 extern cvar_t mod_collision_bih;
11016 void R_DrawDebugModel(void)
11018 entity_render_t *ent = rsurface.entity;
11019 int i, j, k, l, flagsmask;
11020 const msurface_t *surface;
11021 dp_model_t *model = ent->model;
11024 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11027 if (r_showoverdraw.value > 0)
11029 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11030 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11031 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11032 GL_DepthTest(false);
11033 GL_DepthMask(false);
11034 GL_DepthRange(0, 1);
11035 GL_BlendFunc(GL_ONE, GL_ONE);
11036 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11038 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11040 rsurface.texture = R_GetCurrentTexture(surface->texture);
11041 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11043 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11044 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11045 if (!rsurface.texture->currentlayers->depthmask)
11046 GL_Color(c, 0, 0, 1.0f);
11047 else if (ent == r_refdef.scene.worldentity)
11048 GL_Color(c, c, c, 1.0f);
11050 GL_Color(0, c, 0, 1.0f);
11051 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11055 rsurface.texture = NULL;
11058 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11060 // R_Mesh_ResetTextureState();
11061 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11062 GL_DepthRange(0, 1);
11063 GL_DepthTest(!r_showdisabledepthtest.integer);
11064 GL_DepthMask(false);
11065 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11067 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11071 qboolean cullbox = ent == r_refdef.scene.worldentity;
11072 const q3mbrush_t *brush;
11073 const bih_t *bih = &model->collision_bih;
11074 const bih_leaf_t *bihleaf;
11075 float vertex3f[3][3];
11076 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11078 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11080 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11082 switch (bihleaf->type)
11085 brush = model->brush.data_brushes + bihleaf->itemindex;
11086 if (brush->colbrushf && brush->colbrushf->numtriangles)
11088 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);
11089 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11090 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11093 case BIH_COLLISIONTRIANGLE:
11094 triangleindex = bihleaf->itemindex;
11095 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11096 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11097 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11098 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);
11099 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11100 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11102 case BIH_RENDERTRIANGLE:
11103 triangleindex = bihleaf->itemindex;
11104 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11105 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11106 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11107 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);
11108 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11109 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11115 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11117 if (r_showtris.integer && qglPolygonMode)
11119 if (r_showdisabledepthtest.integer)
11121 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11122 GL_DepthMask(false);
11126 GL_BlendFunc(GL_ONE, GL_ZERO);
11127 GL_DepthMask(true);
11129 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11130 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11132 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11134 rsurface.texture = R_GetCurrentTexture(surface->texture);
11135 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11137 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11138 if (!rsurface.texture->currentlayers->depthmask)
11139 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11140 else if (ent == r_refdef.scene.worldentity)
11141 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11143 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11144 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11148 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11149 rsurface.texture = NULL;
11152 if (r_shownormals.value != 0 && qglBegin)
11154 if (r_showdisabledepthtest.integer)
11156 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11157 GL_DepthMask(false);
11161 GL_BlendFunc(GL_ONE, GL_ZERO);
11162 GL_DepthMask(true);
11164 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11166 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11168 rsurface.texture = R_GetCurrentTexture(surface->texture);
11169 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11171 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11172 qglBegin(GL_LINES);
11173 if (r_shownormals.value < 0)
11175 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11177 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11178 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11179 qglVertex3f(v[0], v[1], v[2]);
11180 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11181 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11182 qglVertex3f(v[0], v[1], v[2]);
11185 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11187 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11189 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11190 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11191 qglVertex3f(v[0], v[1], v[2]);
11192 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11193 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11194 qglVertex3f(v[0], v[1], v[2]);
11196 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11198 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11199 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11200 qglVertex3f(v[0], v[1], v[2]);
11201 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11202 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11203 qglVertex3f(v[0], v[1], v[2]);
11205 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11207 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11208 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11209 qglVertex3f(v[0], v[1], v[2]);
11210 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11211 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11212 qglVertex3f(v[0], v[1], v[2]);
11219 rsurface.texture = NULL;
11223 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11224 int r_maxsurfacelist = 0;
11225 const msurface_t **r_surfacelist = NULL;
11226 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11228 int i, j, endj, flagsmask;
11229 dp_model_t *model = r_refdef.scene.worldmodel;
11230 msurface_t *surfaces;
11231 unsigned char *update;
11232 int numsurfacelist = 0;
11236 if (r_maxsurfacelist < model->num_surfaces)
11238 r_maxsurfacelist = model->num_surfaces;
11240 Mem_Free((msurface_t**)r_surfacelist);
11241 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11244 RSurf_ActiveWorldEntity();
11246 surfaces = model->data_surfaces;
11247 update = model->brushq1.lightmapupdateflags;
11249 // update light styles on this submodel
11250 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11252 model_brush_lightstyleinfo_t *style;
11253 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11255 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11257 int *list = style->surfacelist;
11258 style->value = r_refdef.scene.lightstylevalue[style->style];
11259 for (j = 0;j < style->numsurfaces;j++)
11260 update[list[j]] = true;
11265 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11269 R_DrawDebugModel();
11270 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11274 rsurface.lightmaptexture = NULL;
11275 rsurface.deluxemaptexture = NULL;
11276 rsurface.uselightmaptexture = false;
11277 rsurface.texture = NULL;
11278 rsurface.rtlight = NULL;
11279 numsurfacelist = 0;
11280 // add visible surfaces to draw list
11281 for (i = 0;i < model->nummodelsurfaces;i++)
11283 j = model->sortedmodelsurfaces[i];
11284 if (r_refdef.viewcache.world_surfacevisible[j])
11285 r_surfacelist[numsurfacelist++] = surfaces + j;
11287 // update lightmaps if needed
11288 if (model->brushq1.firstrender)
11290 model->brushq1.firstrender = false;
11291 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11293 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11297 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11298 if (r_refdef.viewcache.world_surfacevisible[j])
11300 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11302 // don't do anything if there were no surfaces
11303 if (!numsurfacelist)
11305 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11308 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11310 // add to stats if desired
11311 if (r_speeds.integer && !skysurfaces && !depthonly)
11313 r_refdef.stats.world_surfaces += numsurfacelist;
11314 for (j = 0;j < numsurfacelist;j++)
11315 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11318 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11321 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11323 int i, j, endj, flagsmask;
11324 dp_model_t *model = ent->model;
11325 msurface_t *surfaces;
11326 unsigned char *update;
11327 int numsurfacelist = 0;
11331 if (r_maxsurfacelist < model->num_surfaces)
11333 r_maxsurfacelist = model->num_surfaces;
11335 Mem_Free((msurface_t **)r_surfacelist);
11336 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11339 // if the model is static it doesn't matter what value we give for
11340 // wantnormals and wanttangents, so this logic uses only rules applicable
11341 // to a model, knowing that they are meaningless otherwise
11342 if (ent == r_refdef.scene.worldentity)
11343 RSurf_ActiveWorldEntity();
11344 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11345 RSurf_ActiveModelEntity(ent, false, false, false);
11347 RSurf_ActiveModelEntity(ent, true, true, true);
11348 else if (depthonly)
11350 switch (vid.renderpath)
11352 case RENDERPATH_GL20:
11353 case RENDERPATH_D3D9:
11354 case RENDERPATH_D3D10:
11355 case RENDERPATH_D3D11:
11356 case RENDERPATH_SOFT:
11357 case RENDERPATH_GLES2:
11358 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11360 case RENDERPATH_GL11:
11361 case RENDERPATH_GL13:
11362 case RENDERPATH_GLES1:
11363 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11369 switch (vid.renderpath)
11371 case RENDERPATH_GL20:
11372 case RENDERPATH_D3D9:
11373 case RENDERPATH_D3D10:
11374 case RENDERPATH_D3D11:
11375 case RENDERPATH_SOFT:
11376 case RENDERPATH_GLES2:
11377 RSurf_ActiveModelEntity(ent, true, true, false);
11379 case RENDERPATH_GL11:
11380 case RENDERPATH_GL13:
11381 case RENDERPATH_GLES1:
11382 RSurf_ActiveModelEntity(ent, true, false, false);
11387 surfaces = model->data_surfaces;
11388 update = model->brushq1.lightmapupdateflags;
11390 // update light styles
11391 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11393 model_brush_lightstyleinfo_t *style;
11394 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11396 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11398 int *list = style->surfacelist;
11399 style->value = r_refdef.scene.lightstylevalue[style->style];
11400 for (j = 0;j < style->numsurfaces;j++)
11401 update[list[j]] = true;
11406 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11410 R_DrawDebugModel();
11411 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11415 rsurface.lightmaptexture = NULL;
11416 rsurface.deluxemaptexture = NULL;
11417 rsurface.uselightmaptexture = false;
11418 rsurface.texture = NULL;
11419 rsurface.rtlight = NULL;
11420 numsurfacelist = 0;
11421 // add visible surfaces to draw list
11422 for (i = 0;i < model->nummodelsurfaces;i++)
11423 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11424 // don't do anything if there were no surfaces
11425 if (!numsurfacelist)
11427 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11430 // update lightmaps if needed
11434 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11439 R_BuildLightMap(ent, surfaces + j);
11444 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11446 R_BuildLightMap(ent, surfaces + j);
11447 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11449 // add to stats if desired
11450 if (r_speeds.integer && !skysurfaces && !depthonly)
11452 r_refdef.stats.entities_surfaces += numsurfacelist;
11453 for (j = 0;j < numsurfacelist;j++)
11454 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11457 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11460 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11462 static texture_t texture;
11463 static msurface_t surface;
11464 const msurface_t *surfacelist = &surface;
11466 // fake enough texture and surface state to render this geometry
11468 texture.update_lastrenderframe = -1; // regenerate this texture
11469 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11470 texture.currentskinframe = skinframe;
11471 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11472 texture.offsetmapping = OFFSETMAPPING_OFF;
11473 texture.offsetscale = 1;
11474 texture.specularscalemod = 1;
11475 texture.specularpowermod = 1;
11477 surface.texture = &texture;
11478 surface.num_triangles = numtriangles;
11479 surface.num_firsttriangle = firsttriangle;
11480 surface.num_vertices = numvertices;
11481 surface.num_firstvertex = firstvertex;
11484 rsurface.texture = R_GetCurrentTexture(surface.texture);
11485 rsurface.lightmaptexture = NULL;
11486 rsurface.deluxemaptexture = NULL;
11487 rsurface.uselightmaptexture = false;
11488 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11491 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)
11493 static msurface_t surface;
11494 const msurface_t *surfacelist = &surface;
11496 // fake enough texture and surface state to render this geometry
11497 surface.texture = texture;
11498 surface.num_triangles = numtriangles;
11499 surface.num_firsttriangle = firsttriangle;
11500 surface.num_vertices = numvertices;
11501 surface.num_firstvertex = firstvertex;
11504 rsurface.texture = R_GetCurrentTexture(surface.texture);
11505 rsurface.lightmaptexture = NULL;
11506 rsurface.deluxemaptexture = NULL;
11507 rsurface.uselightmaptexture = false;
11508 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);