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", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 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"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 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)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72 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"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
82 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)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 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"};
86 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"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 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"};
89 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"};
90 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"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 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)"};
99 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)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 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."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 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."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 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"};
123 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"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 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"};
130 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
131 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
133 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
134 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
135 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
136 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
137 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
138 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
139 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
140 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
142 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)"};
143 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"};
145 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
146 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
147 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
149 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"};
150 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"};
151 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
152 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
153 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"};
154 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)"};
155 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)"};
156 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
158 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)"};
159 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
160 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)"};
161 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
162 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)"};
163 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)"};
164 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
165 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
175 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)"};
176 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
177 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"};
178 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
179 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
180 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
181 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
183 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
184 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
185 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
186 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
188 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
189 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
190 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
191 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
192 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
193 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
194 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
196 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
197 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
198 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
199 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)"};
200 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
201 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
202 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
204 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
205 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
206 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
208 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"};
210 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"};
212 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
214 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
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;
224 extern cvar_t v_glslgamma_2d;
226 extern qboolean v_flipped_state;
228 static struct r_bloomstate_s
233 int bloomwidth, bloomheight;
235 textype_t texturetype;
236 int viewfbo; // used to check if r_viewfbo cvar has changed
238 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
239 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
240 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
242 int screentexturewidth, screentextureheight;
243 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
245 int bloomtexturewidth, bloomtextureheight;
246 rtexture_t *texture_bloom;
248 // arrays for rendering the screen passes
249 float screentexcoord2f[8];
250 float bloomtexcoord2f[8];
251 float offsettexcoord2f[8];
253 r_viewport_t viewport;
257 r_waterstate_t r_waterstate;
259 /// shadow volume bsp struct with automatically growing nodes buffer
262 rtexture_t *r_texture_blanknormalmap;
263 rtexture_t *r_texture_white;
264 rtexture_t *r_texture_grey128;
265 rtexture_t *r_texture_black;
266 rtexture_t *r_texture_notexture;
267 rtexture_t *r_texture_whitecube;
268 rtexture_t *r_texture_normalizationcube;
269 rtexture_t *r_texture_fogattenuation;
270 rtexture_t *r_texture_fogheighttexture;
271 rtexture_t *r_texture_gammaramps;
272 unsigned int r_texture_gammaramps_serial;
273 //rtexture_t *r_texture_fogintensity;
274 rtexture_t *r_texture_reflectcube;
276 // TODO: hash lookups?
277 typedef struct cubemapinfo_s
284 int r_texture_numcubemaps;
285 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
287 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
288 unsigned int r_numqueries;
289 unsigned int r_maxqueries;
291 typedef struct r_qwskincache_s
293 char name[MAX_QPATH];
294 skinframe_t *skinframe;
298 static r_qwskincache_t *r_qwskincache;
299 static int r_qwskincache_size;
301 /// vertex coordinates for a quad that covers the screen exactly
302 extern const float r_screenvertex3f[12];
303 extern const float r_d3dscreenvertex3f[12];
304 const float r_screenvertex3f[12] =
311 const float r_d3dscreenvertex3f[12] =
319 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
322 for (i = 0;i < verts;i++)
333 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
336 for (i = 0;i < verts;i++)
346 // FIXME: move this to client?
349 if (gamemode == GAME_NEHAHRA)
351 Cvar_Set("gl_fogenable", "0");
352 Cvar_Set("gl_fogdensity", "0.2");
353 Cvar_Set("gl_fogred", "0.3");
354 Cvar_Set("gl_foggreen", "0.3");
355 Cvar_Set("gl_fogblue", "0.3");
357 r_refdef.fog_density = 0;
358 r_refdef.fog_red = 0;
359 r_refdef.fog_green = 0;
360 r_refdef.fog_blue = 0;
361 r_refdef.fog_alpha = 1;
362 r_refdef.fog_start = 0;
363 r_refdef.fog_end = 16384;
364 r_refdef.fog_height = 1<<30;
365 r_refdef.fog_fadedepth = 128;
366 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
369 static void R_BuildBlankTextures(void)
371 unsigned char data[4];
372 data[2] = 128; // normal X
373 data[1] = 128; // normal Y
374 data[0] = 255; // normal Z
375 data[3] = 128; // height
376 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 static void R_BuildNoTexture(void)
397 unsigned char pix[16][16][4];
398 // this makes a light grey/dark grey checkerboard texture
399 for (y = 0;y < 16;y++)
401 for (x = 0;x < 16;x++)
403 if ((y < 8) ^ (x < 8))
419 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
422 static void R_BuildWhiteCube(void)
424 unsigned char data[6*1*1*4];
425 memset(data, 255, sizeof(data));
426 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
429 static void R_BuildNormalizationCube(void)
433 vec_t s, t, intensity;
436 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
437 for (side = 0;side < 6;side++)
439 for (y = 0;y < NORMSIZE;y++)
441 for (x = 0;x < NORMSIZE;x++)
443 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
479 intensity = 127.0f / sqrt(DotProduct(v, v));
480 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
481 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
482 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
483 data[((side*64+y)*64+x)*4+3] = 255;
487 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
491 static void R_BuildFogTexture(void)
495 unsigned char data1[FOGWIDTH][4];
496 //unsigned char data2[FOGWIDTH][4];
499 r_refdef.fogmasktable_start = r_refdef.fog_start;
500 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
501 r_refdef.fogmasktable_range = r_refdef.fogrange;
502 r_refdef.fogmasktable_density = r_refdef.fog_density;
504 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
505 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
507 d = (x * r - r_refdef.fogmasktable_start);
508 if(developer_extra.integer)
509 Con_DPrintf("%f ", d);
511 if (r_fog_exp2.integer)
512 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
514 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
515 if(developer_extra.integer)
516 Con_DPrintf(" : %f ", alpha);
517 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
518 if(developer_extra.integer)
519 Con_DPrintf(" = %f\n", alpha);
520 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
523 for (x = 0;x < FOGWIDTH;x++)
525 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
530 //data2[x][0] = 255 - b;
531 //data2[x][1] = 255 - b;
532 //data2[x][2] = 255 - b;
535 if (r_texture_fogattenuation)
537 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
543 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
547 static void R_BuildFogHeightTexture(void)
549 unsigned char *inpixels;
557 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
558 if (r_refdef.fogheighttexturename[0])
559 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
562 r_refdef.fog_height_tablesize = 0;
563 if (r_texture_fogheighttexture)
564 R_FreeTexture(r_texture_fogheighttexture);
565 r_texture_fogheighttexture = NULL;
566 if (r_refdef.fog_height_table2d)
567 Mem_Free(r_refdef.fog_height_table2d);
568 r_refdef.fog_height_table2d = NULL;
569 if (r_refdef.fog_height_table1d)
570 Mem_Free(r_refdef.fog_height_table1d);
571 r_refdef.fog_height_table1d = NULL;
575 r_refdef.fog_height_tablesize = size;
576 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
577 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
578 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
580 // LordHavoc: now the magic - what is that table2d for? it is a cooked
581 // average fog color table accounting for every fog layer between a point
582 // and the camera. (Note: attenuation is handled separately!)
583 for (y = 0;y < size;y++)
585 for (x = 0;x < size;x++)
591 for (j = x;j <= y;j++)
593 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599 for (j = x;j >= y;j--)
601 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
606 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
609 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
612 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
615 //=======================================================================================================================================================
617 static const char *builtinshaderstring =
618 #include "shader_glsl.h"
621 const char *builtinhlslshaderstring =
622 #include "shader_hlsl.h"
625 char *glslshaderstring = NULL;
626 char *hlslshaderstring = NULL;
628 //=======================================================================================================================================================
630 typedef struct shaderpermutationinfo_s
635 shaderpermutationinfo_t;
637 typedef struct shadermodeinfo_s
639 const char *vertexfilename;
640 const char *geometryfilename;
641 const char *fragmentfilename;
647 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
648 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {"#define USEDIFFUSE\n", " diffuse"},
651 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
652 {"#define USEVIEWTINT\n", " viewtint"},
653 {"#define USECOLORMAPPING\n", " colormapping"},
654 {"#define USESATURATION\n", " saturation"},
655 {"#define USEFOGINSIDE\n", " foginside"},
656 {"#define USEFOGOUTSIDE\n", " fogoutside"},
657 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
658 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
659 {"#define USEGAMMARAMPS\n", " gammaramps"},
660 {"#define USECUBEFILTER\n", " cubefilter"},
661 {"#define USEGLOW\n", " glow"},
662 {"#define USEBLOOM\n", " bloom"},
663 {"#define USESPECULAR\n", " specular"},
664 {"#define USEPOSTPROCESSING\n", " postprocessing"},
665 {"#define USEREFLECTION\n", " reflection"},
666 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
667 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
668 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
669 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
670 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
671 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
672 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
673 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
674 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
675 {"#define USEALPHAKILL\n", " alphakill"},
676 {"#define USEREFLECTCUBE\n", " reflectcube"},
677 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
678 {"#define USEBOUNCEGRID\n", " bouncegrid"},
679 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
680 {"#define USETRIPPY\n", " trippy"},
683 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
684 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
724 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
725 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
728 struct r_glsl_permutation_s;
729 typedef struct r_glsl_permutation_s
732 struct r_glsl_permutation_s *hashnext;
734 unsigned int permutation;
736 /// indicates if we have tried compiling this permutation already
738 /// 0 if compilation failed
740 // texture units assigned to each detected uniform
741 int tex_Texture_First;
742 int tex_Texture_Second;
743 int tex_Texture_GammaRamps;
744 int tex_Texture_Normal;
745 int tex_Texture_Color;
746 int tex_Texture_Gloss;
747 int tex_Texture_Glow;
748 int tex_Texture_SecondaryNormal;
749 int tex_Texture_SecondaryColor;
750 int tex_Texture_SecondaryGloss;
751 int tex_Texture_SecondaryGlow;
752 int tex_Texture_Pants;
753 int tex_Texture_Shirt;
754 int tex_Texture_FogHeightTexture;
755 int tex_Texture_FogMask;
756 int tex_Texture_Lightmap;
757 int tex_Texture_Deluxemap;
758 int tex_Texture_Attenuation;
759 int tex_Texture_Cube;
760 int tex_Texture_Refraction;
761 int tex_Texture_Reflection;
762 int tex_Texture_ShadowMap2D;
763 int tex_Texture_CubeProjection;
764 int tex_Texture_ScreenDepth;
765 int tex_Texture_ScreenNormalMap;
766 int tex_Texture_ScreenDiffuse;
767 int tex_Texture_ScreenSpecular;
768 int tex_Texture_ReflectMask;
769 int tex_Texture_ReflectCube;
770 int tex_Texture_BounceGrid;
771 /// locations of detected uniforms in program object, or -1 if not found
772 int loc_Texture_First;
773 int loc_Texture_Second;
774 int loc_Texture_GammaRamps;
775 int loc_Texture_Normal;
776 int loc_Texture_Color;
777 int loc_Texture_Gloss;
778 int loc_Texture_Glow;
779 int loc_Texture_SecondaryNormal;
780 int loc_Texture_SecondaryColor;
781 int loc_Texture_SecondaryGloss;
782 int loc_Texture_SecondaryGlow;
783 int loc_Texture_Pants;
784 int loc_Texture_Shirt;
785 int loc_Texture_FogHeightTexture;
786 int loc_Texture_FogMask;
787 int loc_Texture_Lightmap;
788 int loc_Texture_Deluxemap;
789 int loc_Texture_Attenuation;
790 int loc_Texture_Cube;
791 int loc_Texture_Refraction;
792 int loc_Texture_Reflection;
793 int loc_Texture_ShadowMap2D;
794 int loc_Texture_CubeProjection;
795 int loc_Texture_ScreenDepth;
796 int loc_Texture_ScreenNormalMap;
797 int loc_Texture_ScreenDiffuse;
798 int loc_Texture_ScreenSpecular;
799 int loc_Texture_ReflectMask;
800 int loc_Texture_ReflectCube;
801 int loc_Texture_BounceGrid;
803 int loc_BloomBlur_Parameters;
805 int loc_Color_Ambient;
806 int loc_Color_Diffuse;
807 int loc_Color_Specular;
811 int loc_DeferredColor_Ambient;
812 int loc_DeferredColor_Diffuse;
813 int loc_DeferredColor_Specular;
814 int loc_DeferredMod_Diffuse;
815 int loc_DeferredMod_Specular;
816 int loc_DistortScaleRefractReflect;
819 int loc_FogHeightFade;
821 int loc_FogPlaneViewDist;
822 int loc_FogRangeRecip;
825 int loc_LightPosition;
826 int loc_OffsetMapping_ScaleSteps;
828 int loc_ReflectColor;
829 int loc_ReflectFactor;
830 int loc_ReflectOffset;
831 int loc_RefractColor;
833 int loc_ScreenCenterRefractReflect;
834 int loc_ScreenScaleRefractReflect;
835 int loc_ScreenToDepth;
836 int loc_ShadowMap_Parameters;
837 int loc_ShadowMap_TextureScale;
838 int loc_SpecularPower;
843 int loc_ViewTintColor;
845 int loc_ModelToLight;
847 int loc_BackgroundTexMatrix;
848 int loc_ModelViewProjectionMatrix;
849 int loc_ModelViewMatrix;
850 int loc_PixelToScreenTexCoord;
851 int loc_ModelToReflectCube;
852 int loc_ShadowMapMatrix;
853 int loc_BloomColorSubtract;
854 int loc_NormalmapScrollBlend;
855 int loc_BounceGridMatrix;
856 int loc_BounceGridIntensity;
858 r_glsl_permutation_t;
860 #define SHADERPERMUTATION_HASHSIZE 256
863 // non-degradable "lightweight" shader parameters to keep the permutations simpler
864 // these can NOT degrade! only use for simple stuff
867 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
868 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
869 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
870 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
871 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
872 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
873 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
875 #define SHADERSTATICPARMS_COUNT 7
877 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
878 static int shaderstaticparms_count = 0;
880 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
881 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
882 qboolean R_CompileShader_CheckStaticParms(void)
884 static int r_compileshader_staticparms_save[1];
885 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
886 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
889 if (r_glsl_saturation_redcompensate.integer)
890 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
891 if (r_glsl_vertextextureblend_usebothalphas.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
893 if (r_shadow_glossexact.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
895 if (r_glsl_postprocess.integer)
897 if (r_glsl_postprocess_uservec1_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
899 if (r_glsl_postprocess_uservec2_enable.integer)
900 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
901 if (r_glsl_postprocess_uservec3_enable.integer)
902 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
903 if (r_glsl_postprocess_uservec4_enable.integer)
904 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
906 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
909 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
910 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
911 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
913 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
914 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
916 shaderstaticparms_count = 0;
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
920 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
921 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
922 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
923 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
924 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
925 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
928 /// information about each possible shader permutation
929 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
930 /// currently selected permutation
931 r_glsl_permutation_t *r_glsl_permutation;
932 /// storage for permutations linked in the hash table
933 memexpandablearray_t r_glsl_permutationarray;
935 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
937 //unsigned int hashdepth = 0;
938 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
939 r_glsl_permutation_t *p;
940 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
942 if (p->mode == mode && p->permutation == permutation)
944 //if (hashdepth > 10)
945 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
950 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
952 p->permutation = permutation;
953 p->hashnext = r_glsl_permutationhash[mode][hashindex];
954 r_glsl_permutationhash[mode][hashindex] = p;
955 //if (hashdepth > 10)
956 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
960 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
963 if (!filename || !filename[0])
965 if (!strcmp(filename, "glsl/default.glsl"))
967 if (!glslshaderstring)
969 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
970 if (glslshaderstring)
971 Con_DPrintf("Loading shaders from file %s...\n", filename);
973 glslshaderstring = (char *)builtinshaderstring;
975 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
976 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
979 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
982 if (printfromdisknotice)
983 Con_DPrintf("from disk %s... ", filename);
989 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
993 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
994 char *vertexstring, *geometrystring, *fragmentstring;
995 char permutationname[256];
996 int vertstrings_count = 0;
997 int geomstrings_count = 0;
998 int fragstrings_count = 0;
999 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1000 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1001 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1008 permutationname[0] = 0;
1009 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1010 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1011 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1013 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1015 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1016 if(vid.support.gl20shaders130)
1018 vertstrings_list[vertstrings_count++] = "#version 130\n";
1019 geomstrings_list[geomstrings_count++] = "#version 130\n";
1020 fragstrings_list[fragstrings_count++] = "#version 130\n";
1021 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1022 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1023 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1026 // the first pretext is which type of shader to compile as
1027 // (later these will all be bound together as a program object)
1028 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1029 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1030 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1032 // the second pretext is the mode (for example a light source)
1033 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1034 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1035 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1036 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1038 // now add all the permutation pretexts
1039 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1041 if (permutation & (1<<i))
1043 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1044 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1045 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1046 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1050 // keep line numbers correct
1051 vertstrings_list[vertstrings_count++] = "\n";
1052 geomstrings_list[geomstrings_count++] = "\n";
1053 fragstrings_list[fragstrings_count++] = "\n";
1058 R_CompileShader_AddStaticParms(mode, permutation);
1059 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060 vertstrings_count += shaderstaticparms_count;
1061 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062 geomstrings_count += shaderstaticparms_count;
1063 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1064 fragstrings_count += shaderstaticparms_count;
1066 // now append the shader text itself
1067 vertstrings_list[vertstrings_count++] = vertexstring;
1068 geomstrings_list[geomstrings_count++] = geometrystring;
1069 fragstrings_list[fragstrings_count++] = fragmentstring;
1071 // if any sources were NULL, clear the respective list
1073 vertstrings_count = 0;
1074 if (!geometrystring)
1075 geomstrings_count = 0;
1076 if (!fragmentstring)
1077 fragstrings_count = 0;
1079 // compile the shader program
1080 if (vertstrings_count + geomstrings_count + fragstrings_count)
1081 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1085 qglUseProgram(p->program);CHECKGLERROR
1086 // look up all the uniform variable names we care about, so we don't
1087 // have to look them up every time we set them
1089 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1090 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1091 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1092 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1093 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1094 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1095 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1096 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1097 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1098 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1099 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1100 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1101 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1102 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1103 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1104 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1105 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1106 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1107 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1108 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1109 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1110 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1111 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1112 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1113 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1114 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1115 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1116 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1117 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1118 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1119 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1120 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1121 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1122 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1123 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1124 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1125 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1126 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1127 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1128 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1129 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1130 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1131 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1132 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1133 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1134 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1135 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1136 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1137 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1138 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1139 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1140 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1141 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1142 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1143 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1144 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1145 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1146 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1147 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1148 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1149 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1150 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1151 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1152 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1153 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1154 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1155 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1156 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1157 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1158 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1159 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1160 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1161 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1162 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1163 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1164 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1165 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1166 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1167 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1168 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1169 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1170 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1171 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1172 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1173 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1174 // initialize the samplers to refer to the texture units we use
1175 p->tex_Texture_First = -1;
1176 p->tex_Texture_Second = -1;
1177 p->tex_Texture_GammaRamps = -1;
1178 p->tex_Texture_Normal = -1;
1179 p->tex_Texture_Color = -1;
1180 p->tex_Texture_Gloss = -1;
1181 p->tex_Texture_Glow = -1;
1182 p->tex_Texture_SecondaryNormal = -1;
1183 p->tex_Texture_SecondaryColor = -1;
1184 p->tex_Texture_SecondaryGloss = -1;
1185 p->tex_Texture_SecondaryGlow = -1;
1186 p->tex_Texture_Pants = -1;
1187 p->tex_Texture_Shirt = -1;
1188 p->tex_Texture_FogHeightTexture = -1;
1189 p->tex_Texture_FogMask = -1;
1190 p->tex_Texture_Lightmap = -1;
1191 p->tex_Texture_Deluxemap = -1;
1192 p->tex_Texture_Attenuation = -1;
1193 p->tex_Texture_Cube = -1;
1194 p->tex_Texture_Refraction = -1;
1195 p->tex_Texture_Reflection = -1;
1196 p->tex_Texture_ShadowMap2D = -1;
1197 p->tex_Texture_CubeProjection = -1;
1198 p->tex_Texture_ScreenDepth = -1;
1199 p->tex_Texture_ScreenNormalMap = -1;
1200 p->tex_Texture_ScreenDiffuse = -1;
1201 p->tex_Texture_ScreenSpecular = -1;
1202 p->tex_Texture_ReflectMask = -1;
1203 p->tex_Texture_ReflectCube = -1;
1204 p->tex_Texture_BounceGrid = -1;
1206 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1207 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1208 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1209 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1210 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1211 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1212 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1213 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1214 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1215 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1216 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1217 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1218 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1219 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1220 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1221 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1222 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1223 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1224 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1225 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1226 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1227 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1228 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1229 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1230 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1231 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1232 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1233 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1234 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1235 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1237 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1240 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1244 Mem_Free(vertexstring);
1246 Mem_Free(geometrystring);
1248 Mem_Free(fragmentstring);
1251 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1253 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1254 if (r_glsl_permutation != perm)
1256 r_glsl_permutation = perm;
1257 if (!r_glsl_permutation->program)
1259 if (!r_glsl_permutation->compiled)
1260 R_GLSL_CompilePermutation(perm, mode, permutation);
1261 if (!r_glsl_permutation->program)
1263 // remove features until we find a valid permutation
1265 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1267 // reduce i more quickly whenever it would not remove any bits
1268 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1269 if (!(permutation & j))
1272 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1273 if (!r_glsl_permutation->compiled)
1274 R_GLSL_CompilePermutation(perm, mode, permutation);
1275 if (r_glsl_permutation->program)
1278 if (i >= SHADERPERMUTATION_COUNT)
1280 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1281 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1282 qglUseProgram(0);CHECKGLERROR
1283 return; // no bit left to clear, entire mode is broken
1288 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1290 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1291 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1292 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1299 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1300 extern D3DCAPS9 vid_d3d9caps;
1303 struct r_hlsl_permutation_s;
1304 typedef struct r_hlsl_permutation_s
1306 /// hash lookup data
1307 struct r_hlsl_permutation_s *hashnext;
1309 unsigned int permutation;
1311 /// indicates if we have tried compiling this permutation already
1313 /// NULL if compilation failed
1314 IDirect3DVertexShader9 *vertexshader;
1315 IDirect3DPixelShader9 *pixelshader;
1317 r_hlsl_permutation_t;
1319 typedef enum D3DVSREGISTER_e
1321 D3DVSREGISTER_TexMatrix = 0, // float4x4
1322 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1323 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1324 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1325 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1326 D3DVSREGISTER_ModelToLight = 20, // float4x4
1327 D3DVSREGISTER_EyePosition = 24,
1328 D3DVSREGISTER_FogPlane = 25,
1329 D3DVSREGISTER_LightDir = 26,
1330 D3DVSREGISTER_LightPosition = 27,
1334 typedef enum D3DPSREGISTER_e
1336 D3DPSREGISTER_Alpha = 0,
1337 D3DPSREGISTER_BloomBlur_Parameters = 1,
1338 D3DPSREGISTER_ClientTime = 2,
1339 D3DPSREGISTER_Color_Ambient = 3,
1340 D3DPSREGISTER_Color_Diffuse = 4,
1341 D3DPSREGISTER_Color_Specular = 5,
1342 D3DPSREGISTER_Color_Glow = 6,
1343 D3DPSREGISTER_Color_Pants = 7,
1344 D3DPSREGISTER_Color_Shirt = 8,
1345 D3DPSREGISTER_DeferredColor_Ambient = 9,
1346 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1347 D3DPSREGISTER_DeferredColor_Specular = 11,
1348 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1349 D3DPSREGISTER_DeferredMod_Specular = 13,
1350 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1351 D3DPSREGISTER_EyePosition = 15, // unused
1352 D3DPSREGISTER_FogColor = 16,
1353 D3DPSREGISTER_FogHeightFade = 17,
1354 D3DPSREGISTER_FogPlane = 18,
1355 D3DPSREGISTER_FogPlaneViewDist = 19,
1356 D3DPSREGISTER_FogRangeRecip = 20,
1357 D3DPSREGISTER_LightColor = 21,
1358 D3DPSREGISTER_LightDir = 22, // unused
1359 D3DPSREGISTER_LightPosition = 23,
1360 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1361 D3DPSREGISTER_PixelSize = 25,
1362 D3DPSREGISTER_ReflectColor = 26,
1363 D3DPSREGISTER_ReflectFactor = 27,
1364 D3DPSREGISTER_ReflectOffset = 28,
1365 D3DPSREGISTER_RefractColor = 29,
1366 D3DPSREGISTER_Saturation = 30,
1367 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1368 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1369 D3DPSREGISTER_ScreenToDepth = 33,
1370 D3DPSREGISTER_ShadowMap_Parameters = 34,
1371 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1372 D3DPSREGISTER_SpecularPower = 36,
1373 D3DPSREGISTER_UserVec1 = 37,
1374 D3DPSREGISTER_UserVec2 = 38,
1375 D3DPSREGISTER_UserVec3 = 39,
1376 D3DPSREGISTER_UserVec4 = 40,
1377 D3DPSREGISTER_ViewTintColor = 41,
1378 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1379 D3DPSREGISTER_BloomColorSubtract = 43,
1380 D3DPSREGISTER_ViewToLight = 44, // float4x4
1381 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1382 D3DPSREGISTER_NormalmapScrollBlend = 52,
1387 /// information about each possible shader permutation
1388 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1389 /// currently selected permutation
1390 r_hlsl_permutation_t *r_hlsl_permutation;
1391 /// storage for permutations linked in the hash table
1392 memexpandablearray_t r_hlsl_permutationarray;
1394 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1396 //unsigned int hashdepth = 0;
1397 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1398 r_hlsl_permutation_t *p;
1399 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1401 if (p->mode == mode && p->permutation == permutation)
1403 //if (hashdepth > 10)
1404 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1409 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1411 p->permutation = permutation;
1412 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1413 r_hlsl_permutationhash[mode][hashindex] = p;
1414 //if (hashdepth > 10)
1415 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1419 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1422 if (!filename || !filename[0])
1424 if (!strcmp(filename, "hlsl/default.hlsl"))
1426 if (!hlslshaderstring)
1428 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429 if (hlslshaderstring)
1430 Con_DPrintf("Loading shaders from file %s...\n", filename);
1432 hlslshaderstring = (char *)builtinhlslshaderstring;
1434 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1435 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1436 return shaderstring;
1438 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1441 if (printfromdisknotice)
1442 Con_DPrintf("from disk %s... ", filename);
1443 return shaderstring;
1445 return shaderstring;
1449 //#include <d3dx9shader.h>
1450 //#include <d3dx9mesh.h>
1452 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1454 DWORD *vsbin = NULL;
1455 DWORD *psbin = NULL;
1456 fs_offset_t vsbinsize;
1457 fs_offset_t psbinsize;
1458 // IDirect3DVertexShader9 *vs = NULL;
1459 // IDirect3DPixelShader9 *ps = NULL;
1460 ID3DXBuffer *vslog = NULL;
1461 ID3DXBuffer *vsbuffer = NULL;
1462 ID3DXConstantTable *vsconstanttable = NULL;
1463 ID3DXBuffer *pslog = NULL;
1464 ID3DXBuffer *psbuffer = NULL;
1465 ID3DXConstantTable *psconstanttable = NULL;
1468 char temp[MAX_INPUTLINE];
1469 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1470 qboolean debugshader = gl_paranoid.integer != 0;
1471 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1472 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1475 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1476 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1478 if ((!vsbin && vertstring) || (!psbin && fragstring))
1480 const char* dllnames_d3dx9 [] =
1504 dllhandle_t d3dx9_dll = NULL;
1505 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1506 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1507 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1508 dllfunction_t d3dx9_dllfuncs[] =
1510 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1511 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1512 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1515 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1517 DWORD shaderflags = 0;
1519 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1520 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1521 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1522 if (vertstring && vertstring[0])
1526 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1527 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1528 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1529 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1532 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1535 vsbinsize = vsbuffer->GetBufferSize();
1536 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1537 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1538 vsbuffer->Release();
1542 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1543 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1547 if (fragstring && fragstring[0])
1551 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1552 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1553 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1554 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1557 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1560 psbinsize = psbuffer->GetBufferSize();
1561 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1562 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1563 psbuffer->Release();
1567 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1568 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1572 Sys_UnloadLibrary(&d3dx9_dll);
1575 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1579 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1580 if (FAILED(vsresult))
1581 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1582 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1583 if (FAILED(psresult))
1584 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1586 // free the shader data
1587 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1588 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1591 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1594 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1595 int vertstring_length = 0;
1596 int geomstring_length = 0;
1597 int fragstring_length = 0;
1599 char *vertexstring, *geometrystring, *fragmentstring;
1600 char *vertstring, *geomstring, *fragstring;
1601 char permutationname[256];
1602 char cachename[256];
1603 int vertstrings_count = 0;
1604 int geomstrings_count = 0;
1605 int fragstrings_count = 0;
1606 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1613 p->vertexshader = NULL;
1614 p->pixelshader = NULL;
1616 permutationname[0] = 0;
1618 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1619 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1620 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1622 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1623 strlcat(cachename, "hlsl/", sizeof(cachename));
1625 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1626 vertstrings_count = 0;
1627 geomstrings_count = 0;
1628 fragstrings_count = 0;
1629 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1630 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1631 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1633 // the first pretext is which type of shader to compile as
1634 // (later these will all be bound together as a program object)
1635 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1636 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1637 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1639 // the second pretext is the mode (for example a light source)
1640 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1641 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1642 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1643 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1644 strlcat(cachename, modeinfo->name, sizeof(cachename));
1646 // now add all the permutation pretexts
1647 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1649 if (permutation & (1<<i))
1651 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1652 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1653 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1654 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1655 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1659 // keep line numbers correct
1660 vertstrings_list[vertstrings_count++] = "\n";
1661 geomstrings_list[geomstrings_count++] = "\n";
1662 fragstrings_list[fragstrings_count++] = "\n";
1667 R_CompileShader_AddStaticParms(mode, permutation);
1668 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669 vertstrings_count += shaderstaticparms_count;
1670 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671 geomstrings_count += shaderstaticparms_count;
1672 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1673 fragstrings_count += shaderstaticparms_count;
1675 // replace spaces in the cachename with _ characters
1676 for (i = 0;cachename[i];i++)
1677 if (cachename[i] == ' ')
1680 // now append the shader text itself
1681 vertstrings_list[vertstrings_count++] = vertexstring;
1682 geomstrings_list[geomstrings_count++] = geometrystring;
1683 fragstrings_list[fragstrings_count++] = fragmentstring;
1685 // if any sources were NULL, clear the respective list
1687 vertstrings_count = 0;
1688 if (!geometrystring)
1689 geomstrings_count = 0;
1690 if (!fragmentstring)
1691 fragstrings_count = 0;
1693 vertstring_length = 0;
1694 for (i = 0;i < vertstrings_count;i++)
1695 vertstring_length += strlen(vertstrings_list[i]);
1696 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1697 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1698 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1700 geomstring_length = 0;
1701 for (i = 0;i < geomstrings_count;i++)
1702 geomstring_length += strlen(geomstrings_list[i]);
1703 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1704 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1705 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1707 fragstring_length = 0;
1708 for (i = 0;i < fragstrings_count;i++)
1709 fragstring_length += strlen(fragstrings_list[i]);
1710 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1711 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1712 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1714 // try to load the cached shader, or generate one
1715 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1717 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1718 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1720 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1724 Mem_Free(vertstring);
1726 Mem_Free(geomstring);
1728 Mem_Free(fragstring);
1730 Mem_Free(vertexstring);
1732 Mem_Free(geometrystring);
1734 Mem_Free(fragmentstring);
1737 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1738 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1739 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);}
1740 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);}
1741 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);}
1742 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);}
1744 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1745 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1746 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);}
1747 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);}
1748 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);}
1749 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);}
1751 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1753 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1754 if (r_hlsl_permutation != perm)
1756 r_hlsl_permutation = perm;
1757 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1759 if (!r_hlsl_permutation->compiled)
1760 R_HLSL_CompilePermutation(perm, mode, permutation);
1761 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1763 // remove features until we find a valid permutation
1765 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1767 // reduce i more quickly whenever it would not remove any bits
1768 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1769 if (!(permutation & j))
1772 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1773 if (!r_hlsl_permutation->compiled)
1774 R_HLSL_CompilePermutation(perm, mode, permutation);
1775 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1778 if (i >= SHADERPERMUTATION_COUNT)
1780 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1781 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1782 return; // no bit left to clear, entire mode is broken
1786 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1787 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1789 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1790 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1791 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1795 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1797 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1798 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1799 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1800 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1803 void R_GLSL_Restart_f(void)
1805 unsigned int i, limit;
1806 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1807 Mem_Free(glslshaderstring);
1808 glslshaderstring = NULL;
1809 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1810 Mem_Free(hlslshaderstring);
1811 hlslshaderstring = NULL;
1812 switch(vid.renderpath)
1814 case RENDERPATH_D3D9:
1817 r_hlsl_permutation_t *p;
1818 r_hlsl_permutation = NULL;
1819 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1820 for (i = 0;i < limit;i++)
1822 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1824 if (p->vertexshader)
1825 IDirect3DVertexShader9_Release(p->vertexshader);
1827 IDirect3DPixelShader9_Release(p->pixelshader);
1828 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1831 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1835 case RENDERPATH_D3D10:
1836 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1838 case RENDERPATH_D3D11:
1839 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1841 case RENDERPATH_GL20:
1842 case RENDERPATH_GLES2:
1844 r_glsl_permutation_t *p;
1845 r_glsl_permutation = NULL;
1846 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1847 for (i = 0;i < limit;i++)
1849 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1851 GL_Backend_FreeProgram(p->program);
1852 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1855 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1858 case RENDERPATH_GL11:
1859 case RENDERPATH_GL13:
1860 case RENDERPATH_GLES1:
1862 case RENDERPATH_SOFT:
1867 void R_GLSL_DumpShader_f(void)
1872 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1875 FS_Print(file, "/* The engine may define the following macros:\n");
1876 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1877 for (i = 0;i < SHADERMODE_COUNT;i++)
1878 FS_Print(file, glslshadermodeinfo[i].pretext);
1879 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1880 FS_Print(file, shaderpermutationinfo[i].pretext);
1881 FS_Print(file, "*/\n");
1882 FS_Print(file, builtinshaderstring);
1884 Con_Printf("glsl/default.glsl written\n");
1887 Con_Printf("failed to write to glsl/default.glsl\n");
1889 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1892 FS_Print(file, "/* The engine may define the following macros:\n");
1893 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1894 for (i = 0;i < SHADERMODE_COUNT;i++)
1895 FS_Print(file, hlslshadermodeinfo[i].pretext);
1896 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1897 FS_Print(file, shaderpermutationinfo[i].pretext);
1898 FS_Print(file, "*/\n");
1899 FS_Print(file, builtinhlslshaderstring);
1901 Con_Printf("hlsl/default.hlsl written\n");
1904 Con_Printf("failed to write to hlsl/default.hlsl\n");
1907 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1909 unsigned int permutation = 0;
1910 if (r_trippy.integer && !notrippy)
1911 permutation |= SHADERPERMUTATION_TRIPPY;
1912 permutation |= SHADERPERMUTATION_VIEWTINT;
1914 permutation |= SHADERPERMUTATION_DIFFUSE;
1916 permutation |= SHADERPERMUTATION_SPECULAR;
1917 if (texturemode == GL_MODULATE)
1918 permutation |= SHADERPERMUTATION_COLORMAPPING;
1919 else if (texturemode == GL_ADD)
1920 permutation |= SHADERPERMUTATION_GLOW;
1921 else if (texturemode == GL_DECAL)
1922 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1923 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1924 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1926 texturemode = GL_MODULATE;
1927 if (vid.allowalphatocoverage)
1928 GL_AlphaToCoverage(false);
1929 switch (vid.renderpath)
1931 case RENDERPATH_D3D9:
1933 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1934 R_Mesh_TexBind(GL20TU_FIRST , first );
1935 R_Mesh_TexBind(GL20TU_SECOND, second);
1936 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1937 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1940 case RENDERPATH_D3D10:
1941 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1943 case RENDERPATH_D3D11:
1944 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1946 case RENDERPATH_GL20:
1947 case RENDERPATH_GLES2:
1948 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1949 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1950 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1951 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1952 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1954 case RENDERPATH_GL13:
1955 case RENDERPATH_GLES1:
1956 R_Mesh_TexBind(0, first );
1957 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1958 R_Mesh_TexBind(1, second);
1960 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1962 case RENDERPATH_GL11:
1963 R_Mesh_TexBind(0, first );
1965 case RENDERPATH_SOFT:
1966 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1967 R_Mesh_TexBind(GL20TU_FIRST , first );
1968 R_Mesh_TexBind(GL20TU_SECOND, second);
1973 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1975 unsigned int permutation = 0;
1976 if (r_trippy.integer && !notrippy)
1977 permutation |= SHADERPERMUTATION_TRIPPY;
1978 if (vid.allowalphatocoverage)
1979 GL_AlphaToCoverage(false);
1980 switch (vid.renderpath)
1982 case RENDERPATH_D3D9:
1984 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
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_DEPTH_OR_SHADOW, permutation);
1997 case RENDERPATH_GL13:
1998 case RENDERPATH_GLES1:
1999 R_Mesh_TexBind(0, 0);
2000 R_Mesh_TexBind(1, 0);
2002 case RENDERPATH_GL11:
2003 R_Mesh_TexBind(0, 0);
2005 case RENDERPATH_SOFT:
2006 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2011 void R_SetupShader_ShowDepth(qboolean notrippy)
2013 int permutation = 0;
2014 if (r_trippy.integer && !notrippy)
2015 permutation |= SHADERPERMUTATION_TRIPPY;
2016 if (vid.allowalphatocoverage)
2017 GL_AlphaToCoverage(false);
2018 switch (vid.renderpath)
2020 case RENDERPATH_D3D9:
2022 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2025 case RENDERPATH_D3D10:
2026 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2028 case RENDERPATH_D3D11:
2029 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2031 case RENDERPATH_GL20:
2032 case RENDERPATH_GLES2:
2033 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2035 case RENDERPATH_GL13:
2036 case RENDERPATH_GLES1:
2038 case RENDERPATH_GL11:
2040 case RENDERPATH_SOFT:
2041 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2046 extern qboolean r_shadow_usingdeferredprepass;
2047 extern cvar_t r_shadow_deferred_8bitrange;
2048 extern rtexture_t *r_shadow_attenuationgradienttexture;
2049 extern rtexture_t *r_shadow_attenuation2dtexture;
2050 extern rtexture_t *r_shadow_attenuation3dtexture;
2051 extern qboolean r_shadow_usingshadowmap2d;
2052 extern qboolean r_shadow_usingshadowmaportho;
2053 extern float r_shadow_shadowmap_texturescale[2];
2054 extern float r_shadow_shadowmap_parameters[4];
2055 extern qboolean r_shadow_shadowmapvsdct;
2056 extern qboolean r_shadow_shadowmapsampler;
2057 extern int r_shadow_shadowmappcf;
2058 extern rtexture_t *r_shadow_shadowmap2dtexture;
2059 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2060 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2061 extern matrix4x4_t r_shadow_shadowmapmatrix;
2062 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2063 extern int r_shadow_prepass_width;
2064 extern int r_shadow_prepass_height;
2065 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2066 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2067 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2068 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2069 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2071 #define BLENDFUNC_ALLOWS_COLORMOD 1
2072 #define BLENDFUNC_ALLOWS_FOG 2
2073 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2074 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2075 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2076 static int R_BlendFuncFlags(int src, int dst)
2080 // a blendfunc allows colormod if:
2081 // a) it can never keep the destination pixel invariant, or
2082 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2083 // this is to prevent unintended side effects from colormod
2085 // a blendfunc allows fog if:
2086 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2087 // this is to prevent unintended side effects from fog
2089 // these checks are the output of fogeval.pl
2091 r |= BLENDFUNC_ALLOWS_COLORMOD;
2092 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2093 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2094 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2095 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2096 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2097 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2100 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2101 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2102 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2103 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2104 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2105 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2106 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2107 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2111 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2112 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2117 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, qboolean notrippy)
2119 // select a permutation of the lighting shader appropriate to this
2120 // combination of texture, entity, light source, and fogging, only use the
2121 // minimum features necessary to avoid wasting rendering time in the
2122 // fragment shader on features that are not being used
2123 unsigned int permutation = 0;
2124 unsigned int mode = 0;
2126 static float dummy_colormod[3] = {1, 1, 1};
2127 float *colormod = rsurface.colormod;
2129 matrix4x4_t tempmatrix;
2130 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2131 if (r_trippy.integer && !notrippy)
2132 permutation |= SHADERPERMUTATION_TRIPPY;
2133 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2134 permutation |= SHADERPERMUTATION_ALPHAKILL;
2135 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2136 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2137 if (rsurfacepass == RSURFPASS_BACKGROUND)
2139 // distorted background
2140 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2142 mode = SHADERMODE_WATER;
2143 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2145 // this is the right thing to do for wateralpha
2146 GL_BlendFunc(GL_ONE, GL_ZERO);
2147 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2151 // this is the right thing to do for entity alpha
2152 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2153 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2156 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2158 mode = SHADERMODE_REFRACTION;
2159 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2160 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2164 mode = SHADERMODE_GENERIC;
2165 permutation |= SHADERPERMUTATION_DIFFUSE;
2166 GL_BlendFunc(GL_ONE, GL_ZERO);
2167 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2169 if (vid.allowalphatocoverage)
2170 GL_AlphaToCoverage(false);
2172 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2174 if (r_glsl_offsetmapping.integer)
2176 switch(rsurface.texture->offsetmapping)
2178 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2179 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2180 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2181 case OFFSETMAPPING_OFF: break;
2184 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2185 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2186 // normalmap (deferred prepass), may use alpha test on diffuse
2187 mode = SHADERMODE_DEFERREDGEOMETRY;
2188 GL_BlendFunc(GL_ONE, GL_ZERO);
2189 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2190 if (vid.allowalphatocoverage)
2191 GL_AlphaToCoverage(false);
2193 else if (rsurfacepass == RSURFPASS_RTLIGHT)
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;
2208 mode = SHADERMODE_LIGHTSOURCE;
2209 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2210 permutation |= SHADERPERMUTATION_CUBEFILTER;
2211 if (diffusescale > 0)
2212 permutation |= SHADERPERMUTATION_DIFFUSE;
2213 if (specularscale > 0)
2214 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2215 if (r_refdef.fogenabled)
2216 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2217 if (rsurface.texture->colormapping)
2218 permutation |= SHADERPERMUTATION_COLORMAPPING;
2219 if (r_shadow_usingshadowmap2d)
2221 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2222 if(r_shadow_shadowmapvsdct)
2223 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2225 if (r_shadow_shadowmapsampler)
2226 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2227 if (r_shadow_shadowmappcf > 1)
2228 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2229 else if (r_shadow_shadowmappcf)
2230 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2232 if (rsurface.texture->reflectmasktexture)
2233 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2234 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2235 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2236 if (vid.allowalphatocoverage)
2237 GL_AlphaToCoverage(false);
2239 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2241 if (r_glsl_offsetmapping.integer)
2243 switch(rsurface.texture->offsetmapping)
2245 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2246 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2247 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2248 case OFFSETMAPPING_OFF: break;
2251 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2252 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2253 // unshaded geometry (fullbright or ambient model lighting)
2254 mode = SHADERMODE_FLATCOLOR;
2255 ambientscale = diffusescale = specularscale = 0;
2256 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2257 permutation |= SHADERPERMUTATION_GLOW;
2258 if (r_refdef.fogenabled)
2259 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2260 if (rsurface.texture->colormapping)
2261 permutation |= SHADERPERMUTATION_COLORMAPPING;
2262 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2264 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2265 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2267 if (r_shadow_shadowmapsampler)
2268 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2269 if (r_shadow_shadowmappcf > 1)
2270 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2271 else if (r_shadow_shadowmappcf)
2272 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2274 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2275 permutation |= SHADERPERMUTATION_REFLECTION;
2276 if (rsurface.texture->reflectmasktexture)
2277 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2278 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2279 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2280 // when using alphatocoverage, we don't need alphakill
2281 if (vid.allowalphatocoverage)
2283 if (r_transparent_alphatocoverage.integer)
2285 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2286 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2289 GL_AlphaToCoverage(false);
2292 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2294 if (r_glsl_offsetmapping.integer)
2296 switch(rsurface.texture->offsetmapping)
2298 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2299 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301 case OFFSETMAPPING_OFF: break;
2304 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2305 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2306 // directional model lighting
2307 mode = SHADERMODE_LIGHTDIRECTION;
2308 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2309 permutation |= SHADERPERMUTATION_GLOW;
2310 permutation |= SHADERPERMUTATION_DIFFUSE;
2311 if (specularscale > 0)
2312 permutation |= SHADERPERMUTATION_SPECULAR;
2313 if (r_refdef.fogenabled)
2314 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2315 if (rsurface.texture->colormapping)
2316 permutation |= SHADERPERMUTATION_COLORMAPPING;
2317 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2319 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2320 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2322 if (r_shadow_shadowmapsampler)
2323 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2324 if (r_shadow_shadowmappcf > 1)
2325 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2326 else if (r_shadow_shadowmappcf)
2327 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2329 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2330 permutation |= SHADERPERMUTATION_REFLECTION;
2331 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2332 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2333 if (rsurface.texture->reflectmasktexture)
2334 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2335 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2337 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2338 if (r_shadow_bouncegriddirectional)
2339 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2341 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343 // when using alphatocoverage, we don't need alphakill
2344 if (vid.allowalphatocoverage)
2346 if (r_transparent_alphatocoverage.integer)
2348 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2349 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2352 GL_AlphaToCoverage(false);
2355 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2357 if (r_glsl_offsetmapping.integer)
2359 switch(rsurface.texture->offsetmapping)
2361 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2362 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2363 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2364 case OFFSETMAPPING_OFF: break;
2367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2368 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2369 // ambient model lighting
2370 mode = SHADERMODE_LIGHTDIRECTION;
2371 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2372 permutation |= SHADERPERMUTATION_GLOW;
2373 if (r_refdef.fogenabled)
2374 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2375 if (rsurface.texture->colormapping)
2376 permutation |= SHADERPERMUTATION_COLORMAPPING;
2377 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2379 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2380 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2382 if (r_shadow_shadowmapsampler)
2383 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2384 if (r_shadow_shadowmappcf > 1)
2385 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2386 else if (r_shadow_shadowmappcf)
2387 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2389 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2390 permutation |= SHADERPERMUTATION_REFLECTION;
2391 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2392 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2393 if (rsurface.texture->reflectmasktexture)
2394 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2395 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2397 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2398 if (r_shadow_bouncegriddirectional)
2399 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2401 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2402 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2403 // when using alphatocoverage, we don't need alphakill
2404 if (vid.allowalphatocoverage)
2406 if (r_transparent_alphatocoverage.integer)
2408 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2409 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2412 GL_AlphaToCoverage(false);
2417 if (r_glsl_offsetmapping.integer)
2419 switch(rsurface.texture->offsetmapping)
2421 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2422 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2423 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2424 case OFFSETMAPPING_OFF: break;
2427 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2428 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2430 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2431 permutation |= SHADERPERMUTATION_GLOW;
2432 if (r_refdef.fogenabled)
2433 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2434 if (rsurface.texture->colormapping)
2435 permutation |= SHADERPERMUTATION_COLORMAPPING;
2436 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2438 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2439 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2441 if (r_shadow_shadowmapsampler)
2442 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2443 if (r_shadow_shadowmappcf > 1)
2444 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2445 else if (r_shadow_shadowmappcf)
2446 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2448 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2449 permutation |= SHADERPERMUTATION_REFLECTION;
2450 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2451 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2452 if (rsurface.texture->reflectmasktexture)
2453 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2454 if (FAKELIGHT_ENABLED)
2456 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2457 mode = SHADERMODE_FAKELIGHT;
2458 permutation |= SHADERPERMUTATION_DIFFUSE;
2459 if (specularscale > 0)
2460 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2462 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2464 // deluxemapping (light direction texture)
2465 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2466 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2468 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2469 permutation |= SHADERPERMUTATION_DIFFUSE;
2470 if (specularscale > 0)
2471 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2473 else if (r_glsl_deluxemapping.integer >= 2)
2475 // fake deluxemapping (uniform light direction in tangentspace)
2476 if (rsurface.uselightmaptexture)
2477 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2479 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2480 permutation |= SHADERPERMUTATION_DIFFUSE;
2481 if (specularscale > 0)
2482 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2484 else if (rsurface.uselightmaptexture)
2486 // ordinary lightmapping (q1bsp, q3bsp)
2487 mode = SHADERMODE_LIGHTMAP;
2491 // ordinary vertex coloring (q3bsp)
2492 mode = SHADERMODE_VERTEXCOLOR;
2494 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2496 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2497 if (r_shadow_bouncegriddirectional)
2498 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2500 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2501 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2502 // when using alphatocoverage, we don't need alphakill
2503 if (vid.allowalphatocoverage)
2505 if (r_transparent_alphatocoverage.integer)
2507 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2508 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2511 GL_AlphaToCoverage(false);
2514 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2515 colormod = dummy_colormod;
2516 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2517 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2518 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2519 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2520 switch(vid.renderpath)
2522 case RENDERPATH_D3D9:
2524 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);
2525 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2526 R_SetupShader_SetPermutationHLSL(mode, permutation);
2527 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2528 if (mode == SHADERMODE_LIGHTSOURCE)
2530 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2531 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2535 if (mode == SHADERMODE_LIGHTDIRECTION)
2537 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2540 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2541 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2542 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2543 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2544 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2546 if (mode == SHADERMODE_LIGHTSOURCE)
2548 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2549 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2550 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2551 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2552 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2554 // additive passes are only darkened by fog, not tinted
2555 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2556 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2560 if (mode == SHADERMODE_FLATCOLOR)
2562 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2564 else if (mode == SHADERMODE_LIGHTDIRECTION)
2566 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]);
2567 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2568 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);
2569 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);
2570 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2571 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2572 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2576 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2577 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2578 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);
2579 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);
2580 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2582 // additive passes are only darkened by fog, not tinted
2583 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2584 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2586 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2587 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);
2588 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2589 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2590 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2591 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2592 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2593 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2594 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2595 if (mode == SHADERMODE_WATER)
2596 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2598 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2599 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2600 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2601 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));
2602 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2603 if (rsurface.texture->pantstexture)
2604 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2606 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2607 if (rsurface.texture->shirttexture)
2608 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2610 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2611 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2612 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2613 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2614 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2615 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2616 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2617 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2618 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2619 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2621 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2622 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2624 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2625 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2626 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2627 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2628 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2629 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2630 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2631 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2632 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2633 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2634 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2635 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2636 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2637 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2638 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2639 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2640 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2641 if (rsurfacepass == RSURFPASS_BACKGROUND)
2643 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2644 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2645 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2649 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2651 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2652 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2653 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2654 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2655 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2657 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2658 if (rsurface.rtlight)
2660 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2661 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2666 case RENDERPATH_D3D10:
2667 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2669 case RENDERPATH_D3D11:
2670 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2672 case RENDERPATH_GL20:
2673 case RENDERPATH_GLES2:
2674 if (!vid.useinterleavedarrays)
2676 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);
2677 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2678 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2679 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2680 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2681 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2682 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2683 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2687 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);
2688 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2690 R_SetupShader_SetPermutationGLSL(mode, permutation);
2691 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2692 if (mode == SHADERMODE_LIGHTSOURCE)
2694 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2695 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2696 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2697 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2698 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2699 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);
2701 // additive passes are only darkened by fog, not tinted
2702 if (r_glsl_permutation->loc_FogColor >= 0)
2703 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2704 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2708 if (mode == SHADERMODE_FLATCOLOR)
2710 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2712 else if (mode == SHADERMODE_LIGHTDIRECTION)
2714 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]);
2715 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]);
2716 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);
2717 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);
2718 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);
2719 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]);
2720 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]);
2724 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]);
2725 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]);
2726 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);
2727 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);
2728 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);
2730 // additive passes are only darkened by fog, not tinted
2731 if (r_glsl_permutation->loc_FogColor >= 0)
2733 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2734 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2736 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2738 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);
2739 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]);
2740 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]);
2741 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]);
2742 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]);
2743 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2744 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2745 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2746 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]);
2748 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2749 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2750 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2751 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]);
2752 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]);
2754 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2755 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));
2756 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2757 if (r_glsl_permutation->loc_Color_Pants >= 0)
2759 if (rsurface.texture->pantstexture)
2760 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2762 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2764 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2766 if (rsurface.texture->shirttexture)
2767 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2769 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2771 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]);
2772 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2773 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2774 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2775 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2776 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2777 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2778 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2779 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2781 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]);
2782 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2783 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);}
2784 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2786 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2787 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2788 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2789 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2790 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2791 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2792 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2793 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2794 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2795 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2796 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2797 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2798 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2799 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2800 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);
2801 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2802 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2803 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2804 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2805 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2806 if (rsurfacepass == RSURFPASS_BACKGROUND)
2808 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);
2809 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);
2810 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);
2814 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);
2816 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2817 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2818 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2819 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2820 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2822 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2823 if (rsurface.rtlight)
2825 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2826 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2829 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2832 case RENDERPATH_GL11:
2833 case RENDERPATH_GL13:
2834 case RENDERPATH_GLES1:
2836 case RENDERPATH_SOFT:
2837 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);
2838 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2839 R_SetupShader_SetPermutationSoft(mode, permutation);
2840 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2841 if (mode == SHADERMODE_LIGHTSOURCE)
2843 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2844 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2845 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2846 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2847 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2848 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2850 // additive passes are only darkened by fog, not tinted
2851 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2852 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2856 if (mode == SHADERMODE_FLATCOLOR)
2858 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2860 else if (mode == SHADERMODE_LIGHTDIRECTION)
2862 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]);
2863 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2864 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);
2865 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);
2866 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2867 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]);
2868 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2872 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2873 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2874 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);
2875 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);
2876 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2878 // additive passes are only darkened by fog, not tinted
2879 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2880 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2882 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2883 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);
2884 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2885 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2886 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]);
2887 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]);
2888 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2889 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2890 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2891 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2893 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2894 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2895 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2896 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2897 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]);
2899 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2900 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));
2901 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2902 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2904 if (rsurface.texture->pantstexture)
2905 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2907 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2909 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2911 if (rsurface.texture->shirttexture)
2912 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2914 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2916 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2917 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2918 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2919 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2920 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2921 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2922 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2923 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2924 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2926 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2927 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2929 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2930 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2931 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2932 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2933 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2934 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2935 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2936 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2937 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2938 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2939 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2940 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2941 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2942 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2943 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2944 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2945 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2946 if (rsurfacepass == RSURFPASS_BACKGROUND)
2948 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2949 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2950 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2954 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2956 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2957 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2958 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2959 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2960 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2962 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2963 if (rsurface.rtlight)
2965 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2966 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2973 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2975 // select a permutation of the lighting shader appropriate to this
2976 // combination of texture, entity, light source, and fogging, only use the
2977 // minimum features necessary to avoid wasting rendering time in the
2978 // fragment shader on features that are not being used
2979 unsigned int permutation = 0;
2980 unsigned int mode = 0;
2981 const float *lightcolorbase = rtlight->currentcolor;
2982 float ambientscale = rtlight->ambientscale;
2983 float diffusescale = rtlight->diffusescale;
2984 float specularscale = rtlight->specularscale;
2985 // this is the location of the light in view space
2986 vec3_t viewlightorigin;
2987 // this transforms from view space (camera) to light space (cubemap)
2988 matrix4x4_t viewtolight;
2989 matrix4x4_t lighttoview;
2990 float viewtolight16f[16];
2991 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2993 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2994 if (rtlight->currentcubemap != r_texture_whitecube)
2995 permutation |= SHADERPERMUTATION_CUBEFILTER;
2996 if (diffusescale > 0)
2997 permutation |= SHADERPERMUTATION_DIFFUSE;
2998 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2999 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3000 if (r_shadow_usingshadowmap2d)
3002 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3003 if (r_shadow_shadowmapvsdct)
3004 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3006 if (r_shadow_shadowmapsampler)
3007 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3008 if (r_shadow_shadowmappcf > 1)
3009 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3010 else if (r_shadow_shadowmappcf)
3011 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3013 if (vid.allowalphatocoverage)
3014 GL_AlphaToCoverage(false);
3015 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3016 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3017 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3018 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3019 switch(vid.renderpath)
3021 case RENDERPATH_D3D9:
3023 R_SetupShader_SetPermutationHLSL(mode, permutation);
3024 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3025 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3026 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3027 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3028 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3029 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3030 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3031 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3032 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3033 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3035 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3036 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3037 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3038 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3039 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3040 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3043 case RENDERPATH_D3D10:
3044 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3046 case RENDERPATH_D3D11:
3047 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3049 case RENDERPATH_GL20:
3050 case RENDERPATH_GLES2:
3051 R_SetupShader_SetPermutationGLSL(mode, permutation);
3052 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3053 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3054 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);
3055 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);
3056 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);
3057 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]);
3058 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]);
3059 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) - 1.0f);
3060 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]);
3061 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3063 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3064 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3065 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3066 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3067 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3068 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3070 case RENDERPATH_GL11:
3071 case RENDERPATH_GL13:
3072 case RENDERPATH_GLES1:
3074 case RENDERPATH_SOFT:
3075 R_SetupShader_SetPermutationGLSL(mode, permutation);
3076 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3077 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3078 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3079 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3080 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3081 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3082 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]);
3083 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) - 1.0f);
3084 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3085 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3087 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3088 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3089 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3090 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3091 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3092 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3097 #define SKINFRAME_HASH 1024
3101 int loadsequence; // incremented each level change
3102 memexpandablearray_t array;
3103 skinframe_t *hash[SKINFRAME_HASH];
3106 r_skinframe_t r_skinframe;
3108 void R_SkinFrame_PrepareForPurge(void)
3110 r_skinframe.loadsequence++;
3111 // wrap it without hitting zero
3112 if (r_skinframe.loadsequence >= 200)
3113 r_skinframe.loadsequence = 1;
3116 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3120 // mark the skinframe as used for the purging code
3121 skinframe->loadsequence = r_skinframe.loadsequence;
3124 void R_SkinFrame_Purge(void)
3128 for (i = 0;i < SKINFRAME_HASH;i++)
3130 for (s = r_skinframe.hash[i];s;s = s->next)
3132 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3134 if (s->merged == s->base)
3136 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3137 R_PurgeTexture(s->stain );s->stain = NULL;
3138 R_PurgeTexture(s->merged);s->merged = NULL;
3139 R_PurgeTexture(s->base );s->base = NULL;
3140 R_PurgeTexture(s->pants );s->pants = NULL;
3141 R_PurgeTexture(s->shirt );s->shirt = NULL;
3142 R_PurgeTexture(s->nmap );s->nmap = NULL;
3143 R_PurgeTexture(s->gloss );s->gloss = NULL;
3144 R_PurgeTexture(s->glow );s->glow = NULL;
3145 R_PurgeTexture(s->fog );s->fog = NULL;
3146 R_PurgeTexture(s->reflect);s->reflect = NULL;
3147 s->loadsequence = 0;
3153 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3155 char basename[MAX_QPATH];
3157 Image_StripImageExtension(name, basename, sizeof(basename));
3159 if( last == NULL ) {
3161 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3162 item = r_skinframe.hash[hashindex];
3167 // linearly search through the hash bucket
3168 for( ; item ; item = item->next ) {
3169 if( !strcmp( item->basename, basename ) ) {
3176 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3180 char basename[MAX_QPATH];
3182 Image_StripImageExtension(name, basename, sizeof(basename));
3184 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3185 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3186 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3190 rtexture_t *dyntexture;
3191 // check whether its a dynamic texture
3192 dyntexture = CL_GetDynTexture( basename );
3193 if (!add && !dyntexture)
3195 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3196 memset(item, 0, sizeof(*item));
3197 strlcpy(item->basename, basename, sizeof(item->basename));
3198 item->base = dyntexture; // either NULL or dyntexture handle
3199 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3200 item->comparewidth = comparewidth;
3201 item->compareheight = compareheight;
3202 item->comparecrc = comparecrc;
3203 item->next = r_skinframe.hash[hashindex];
3204 r_skinframe.hash[hashindex] = item;
3206 else if (textureflags & TEXF_FORCE_RELOAD)
3208 rtexture_t *dyntexture;
3209 // check whether its a dynamic texture
3210 dyntexture = CL_GetDynTexture( basename );
3211 if (!add && !dyntexture)
3213 if (item->merged == item->base)
3214 item->merged = NULL;
3215 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3216 R_PurgeTexture(item->stain );item->stain = NULL;
3217 R_PurgeTexture(item->merged);item->merged = NULL;
3218 R_PurgeTexture(item->base );item->base = NULL;
3219 R_PurgeTexture(item->pants );item->pants = NULL;
3220 R_PurgeTexture(item->shirt );item->shirt = NULL;
3221 R_PurgeTexture(item->nmap );item->nmap = NULL;
3222 R_PurgeTexture(item->gloss );item->gloss = NULL;
3223 R_PurgeTexture(item->glow );item->glow = NULL;
3224 R_PurgeTexture(item->fog );item->fog = NULL;
3225 R_PurgeTexture(item->reflect);item->reflect = NULL;
3226 item->loadsequence = 0;
3228 else if( item->base == NULL )
3230 rtexture_t *dyntexture;
3231 // check whether its a dynamic texture
3232 // 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]
3233 dyntexture = CL_GetDynTexture( basename );
3234 item->base = dyntexture; // either NULL or dyntexture handle
3237 R_SkinFrame_MarkUsed(item);
3241 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3243 unsigned long long avgcolor[5], wsum; \
3251 for(pix = 0; pix < cnt; ++pix) \
3254 for(comp = 0; comp < 3; ++comp) \
3256 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3259 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3261 for(comp = 0; comp < 3; ++comp) \
3262 avgcolor[comp] += getpixel * w; \
3265 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3266 avgcolor[4] += getpixel; \
3268 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3270 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3271 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3272 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3273 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3276 extern cvar_t gl_picmip;
3277 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3280 unsigned char *pixels;
3281 unsigned char *bumppixels;
3282 unsigned char *basepixels = NULL;
3283 int basepixels_width = 0;
3284 int basepixels_height = 0;
3285 skinframe_t *skinframe;
3286 rtexture_t *ddsbase = NULL;
3287 qboolean ddshasalpha = false;
3288 float ddsavgcolor[4];
3289 char basename[MAX_QPATH];
3290 int miplevel = R_PicmipForFlags(textureflags);
3291 int savemiplevel = miplevel;
3294 if (cls.state == ca_dedicated)
3297 // return an existing skinframe if already loaded
3298 // if loading of the first image fails, don't make a new skinframe as it
3299 // would cause all future lookups of this to be missing
3300 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3301 if (skinframe && skinframe->base)
3304 Image_StripImageExtension(name, basename, sizeof(basename));
3306 // check for DDS texture file first
3307 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3309 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3310 if (basepixels == NULL)
3314 // FIXME handle miplevel
3316 if (developer_loading.integer)
3317 Con_Printf("loading skin \"%s\"\n", name);
3319 // we've got some pixels to store, so really allocate this new texture now
3321 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3322 textureflags &= ~TEXF_FORCE_RELOAD;
3323 skinframe->stain = NULL;
3324 skinframe->merged = NULL;
3325 skinframe->base = NULL;
3326 skinframe->pants = NULL;
3327 skinframe->shirt = NULL;
3328 skinframe->nmap = NULL;
3329 skinframe->gloss = NULL;
3330 skinframe->glow = NULL;
3331 skinframe->fog = NULL;
3332 skinframe->reflect = NULL;
3333 skinframe->hasalpha = false;
3337 skinframe->base = ddsbase;
3338 skinframe->hasalpha = ddshasalpha;
3339 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3340 if (r_loadfog && skinframe->hasalpha)
3341 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3342 //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]);
3346 basepixels_width = image_width;
3347 basepixels_height = image_height;
3348 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);
3349 if (textureflags & TEXF_ALPHA)
3351 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3353 if (basepixels[j] < 255)
3355 skinframe->hasalpha = true;
3359 if (r_loadfog && skinframe->hasalpha)
3361 // has transparent pixels
3362 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3363 for (j = 0;j < image_width * image_height * 4;j += 4)
3368 pixels[j+3] = basepixels[j+3];
3370 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);
3374 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3376 //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]);
3377 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3378 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3379 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3380 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3386 mymiplevel = savemiplevel;
3387 if (r_loadnormalmap)
3388 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);
3389 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3391 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3392 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3393 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3394 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3397 // _norm is the name used by tenebrae and has been adopted as standard
3398 if (r_loadnormalmap && skinframe->nmap == NULL)
3400 mymiplevel = savemiplevel;
3401 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3403 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);
3407 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3409 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3410 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3411 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);
3413 Mem_Free(bumppixels);
3415 else if (r_shadow_bumpscale_basetexture.value > 0)
3417 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3418 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3419 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);
3423 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3424 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3428 // _luma is supported only for tenebrae compatibility
3429 // _glow is the preferred name
3430 mymiplevel = savemiplevel;
3431 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))))
3433 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);
3435 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3436 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3438 Mem_Free(pixels);pixels = NULL;
3441 mymiplevel = savemiplevel;
3442 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3444 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3446 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3447 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3453 mymiplevel = savemiplevel;
3454 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3456 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);
3458 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3459 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3465 mymiplevel = savemiplevel;
3466 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3468 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);
3470 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3471 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3477 mymiplevel = savemiplevel;
3478 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3480 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);
3482 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3483 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3490 Mem_Free(basepixels);
3495 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3496 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3499 unsigned char *temp1, *temp2;
3500 skinframe_t *skinframe;
3502 if (cls.state == ca_dedicated)
3505 // if already loaded just return it, otherwise make a new skinframe
3506 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3507 if (skinframe && skinframe->base)
3509 textureflags &= ~TEXF_FORCE_RELOAD;
3511 skinframe->stain = NULL;
3512 skinframe->merged = NULL;
3513 skinframe->base = NULL;
3514 skinframe->pants = NULL;
3515 skinframe->shirt = NULL;
3516 skinframe->nmap = NULL;
3517 skinframe->gloss = NULL;
3518 skinframe->glow = NULL;
3519 skinframe->fog = NULL;
3520 skinframe->reflect = NULL;
3521 skinframe->hasalpha = false;
3523 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3527 if (developer_loading.integer)
3528 Con_Printf("loading 32bit skin \"%s\"\n", name);
3530 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3532 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3533 temp2 = temp1 + width * height * 4;
3534 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3535 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);
3538 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3539 if (textureflags & TEXF_ALPHA)
3541 for (i = 3;i < width * height * 4;i += 4)
3543 if (skindata[i] < 255)
3545 skinframe->hasalpha = true;
3549 if (r_loadfog && skinframe->hasalpha)
3551 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3552 memcpy(fogpixels, skindata, width * height * 4);
3553 for (i = 0;i < width * height * 4;i += 4)
3554 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3555 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3556 Mem_Free(fogpixels);
3560 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3561 //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]);
3566 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3570 skinframe_t *skinframe;
3572 if (cls.state == ca_dedicated)
3575 // if already loaded just return it, otherwise make a new skinframe
3576 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3577 if (skinframe && skinframe->base)
3579 textureflags &= ~TEXF_FORCE_RELOAD;
3581 skinframe->stain = NULL;
3582 skinframe->merged = NULL;
3583 skinframe->base = NULL;
3584 skinframe->pants = NULL;
3585 skinframe->shirt = NULL;
3586 skinframe->nmap = NULL;
3587 skinframe->gloss = NULL;
3588 skinframe->glow = NULL;
3589 skinframe->fog = NULL;
3590 skinframe->reflect = NULL;
3591 skinframe->hasalpha = false;
3593 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3597 if (developer_loading.integer)
3598 Con_Printf("loading quake skin \"%s\"\n", name);
3600 // 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)
3601 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3602 memcpy(skinframe->qpixels, skindata, width*height);
3603 skinframe->qwidth = width;
3604 skinframe->qheight = height;
3607 for (i = 0;i < width * height;i++)
3608 featuresmask |= palette_featureflags[skindata[i]];
3610 skinframe->hasalpha = false;
3611 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3612 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3613 skinframe->qgeneratemerged = true;
3614 skinframe->qgeneratebase = skinframe->qhascolormapping;
3615 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3617 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3618 //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]);
3623 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3627 unsigned char *skindata;
3629 if (!skinframe->qpixels)
3632 if (!skinframe->qhascolormapping)
3633 colormapped = false;
3637 if (!skinframe->qgeneratebase)
3642 if (!skinframe->qgeneratemerged)
3646 width = skinframe->qwidth;
3647 height = skinframe->qheight;
3648 skindata = skinframe->qpixels;
3650 if (skinframe->qgeneratenmap)
3652 unsigned char *temp1, *temp2;
3653 skinframe->qgeneratenmap = false;
3654 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3655 temp2 = temp1 + width * height * 4;
3656 // use either a custom palette or the quake palette
3657 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3658 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3659 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);
3663 if (skinframe->qgenerateglow)
3665 skinframe->qgenerateglow = false;
3666 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
3671 skinframe->qgeneratebase = false;
3672 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);
3673 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);
3674 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);
3678 skinframe->qgeneratemerged = false;
3679 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);
3682 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3684 Mem_Free(skinframe->qpixels);
3685 skinframe->qpixels = NULL;
3689 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)
3692 skinframe_t *skinframe;
3694 if (cls.state == ca_dedicated)
3697 // if already loaded just return it, otherwise make a new skinframe
3698 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3699 if (skinframe && skinframe->base)
3701 textureflags &= ~TEXF_FORCE_RELOAD;
3703 skinframe->stain = NULL;
3704 skinframe->merged = NULL;
3705 skinframe->base = NULL;
3706 skinframe->pants = NULL;
3707 skinframe->shirt = NULL;
3708 skinframe->nmap = NULL;
3709 skinframe->gloss = NULL;
3710 skinframe->glow = NULL;
3711 skinframe->fog = NULL;
3712 skinframe->reflect = NULL;
3713 skinframe->hasalpha = false;
3715 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3719 if (developer_loading.integer)
3720 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3722 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3723 if (textureflags & TEXF_ALPHA)
3725 for (i = 0;i < width * height;i++)
3727 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3729 skinframe->hasalpha = true;
3733 if (r_loadfog && skinframe->hasalpha)
3734 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3737 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3738 //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]);
3743 skinframe_t *R_SkinFrame_LoadMissing(void)
3745 skinframe_t *skinframe;
3747 if (cls.state == ca_dedicated)
3750 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3751 skinframe->stain = NULL;
3752 skinframe->merged = NULL;
3753 skinframe->base = NULL;
3754 skinframe->pants = NULL;
3755 skinframe->shirt = NULL;
3756 skinframe->nmap = NULL;
3757 skinframe->gloss = NULL;
3758 skinframe->glow = NULL;
3759 skinframe->fog = NULL;
3760 skinframe->reflect = NULL;
3761 skinframe->hasalpha = false;
3763 skinframe->avgcolor[0] = rand() / RAND_MAX;
3764 skinframe->avgcolor[1] = rand() / RAND_MAX;
3765 skinframe->avgcolor[2] = rand() / RAND_MAX;
3766 skinframe->avgcolor[3] = 1;
3771 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3772 typedef struct suffixinfo_s
3775 qboolean flipx, flipy, flipdiagonal;
3778 static suffixinfo_t suffix[3][6] =
3781 {"px", false, false, false},
3782 {"nx", false, false, false},
3783 {"py", false, false, false},
3784 {"ny", false, false, false},
3785 {"pz", false, false, false},
3786 {"nz", false, false, false}
3789 {"posx", false, false, false},
3790 {"negx", false, false, false},
3791 {"posy", false, false, false},
3792 {"negy", false, false, false},
3793 {"posz", false, false, false},
3794 {"negz", false, false, false}
3797 {"rt", true, false, true},
3798 {"lf", false, true, true},
3799 {"ft", true, true, false},
3800 {"bk", false, false, false},
3801 {"up", true, false, true},
3802 {"dn", true, false, true}
3806 static int componentorder[4] = {0, 1, 2, 3};
3808 rtexture_t *R_LoadCubemap(const char *basename)
3810 int i, j, cubemapsize;
3811 unsigned char *cubemappixels, *image_buffer;
3812 rtexture_t *cubemaptexture;
3814 // must start 0 so the first loadimagepixels has no requested width/height
3816 cubemappixels = NULL;
3817 cubemaptexture = NULL;
3818 // keep trying different suffix groups (posx, px, rt) until one loads
3819 for (j = 0;j < 3 && !cubemappixels;j++)
3821 // load the 6 images in the suffix group
3822 for (i = 0;i < 6;i++)
3824 // generate an image name based on the base and and suffix
3825 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3827 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3829 // an image loaded, make sure width and height are equal
3830 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3832 // if this is the first image to load successfully, allocate the cubemap memory
3833 if (!cubemappixels && image_width >= 1)
3835 cubemapsize = image_width;
3836 // note this clears to black, so unavailable sides are black
3837 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3839 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3841 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);
3844 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3846 Mem_Free(image_buffer);
3850 // if a cubemap loaded, upload it
3853 if (developer_loading.integer)
3854 Con_Printf("loading cubemap \"%s\"\n", basename);
3856 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);
3857 Mem_Free(cubemappixels);
3861 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3862 if (developer_loading.integer)
3864 Con_Printf("(tried tried images ");
3865 for (j = 0;j < 3;j++)
3866 for (i = 0;i < 6;i++)
3867 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3868 Con_Print(" and was unable to find any of them).\n");
3871 return cubemaptexture;
3874 rtexture_t *R_GetCubemap(const char *basename)
3877 for (i = 0;i < r_texture_numcubemaps;i++)
3878 if (r_texture_cubemaps[i] != NULL)
3879 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3880 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3881 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3882 return r_texture_whitecube;
3883 r_texture_numcubemaps++;
3884 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3885 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3886 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3887 return r_texture_cubemaps[i]->texture;
3890 void R_FreeCubemap(const char *basename)
3894 for (i = 0;i < r_texture_numcubemaps;i++)
3896 if (r_texture_cubemaps[i] != NULL)
3898 if (r_texture_cubemaps[i]->texture)
3900 if (developer_loading.integer)
3901 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3902 R_FreeTexture(r_texture_cubemaps[i]->texture);
3903 Mem_Free(r_texture_cubemaps[i]);
3904 r_texture_cubemaps[i] = NULL;
3910 void R_FreeCubemaps(void)
3913 for (i = 0;i < r_texture_numcubemaps;i++)
3915 if (developer_loading.integer)
3916 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3917 if (r_texture_cubemaps[i] != NULL)
3919 if (r_texture_cubemaps[i]->texture)
3920 R_FreeTexture(r_texture_cubemaps[i]->texture);
3921 Mem_Free(r_texture_cubemaps[i]);
3924 r_texture_numcubemaps = 0;
3927 void R_Main_FreeViewCache(void)
3929 if (r_refdef.viewcache.entityvisible)
3930 Mem_Free(r_refdef.viewcache.entityvisible);
3931 if (r_refdef.viewcache.world_pvsbits)
3932 Mem_Free(r_refdef.viewcache.world_pvsbits);
3933 if (r_refdef.viewcache.world_leafvisible)
3934 Mem_Free(r_refdef.viewcache.world_leafvisible);
3935 if (r_refdef.viewcache.world_surfacevisible)
3936 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3937 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3940 void R_Main_ResizeViewCache(void)
3942 int numentities = r_refdef.scene.numentities;
3943 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3944 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3945 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3946 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3947 if (r_refdef.viewcache.maxentities < numentities)
3949 r_refdef.viewcache.maxentities = numentities;
3950 if (r_refdef.viewcache.entityvisible)
3951 Mem_Free(r_refdef.viewcache.entityvisible);
3952 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3954 if (r_refdef.viewcache.world_numclusters != numclusters)
3956 r_refdef.viewcache.world_numclusters = numclusters;
3957 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3958 if (r_refdef.viewcache.world_pvsbits)
3959 Mem_Free(r_refdef.viewcache.world_pvsbits);
3960 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3962 if (r_refdef.viewcache.world_numleafs != numleafs)
3964 r_refdef.viewcache.world_numleafs = numleafs;
3965 if (r_refdef.viewcache.world_leafvisible)
3966 Mem_Free(r_refdef.viewcache.world_leafvisible);
3967 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3969 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3971 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3972 if (r_refdef.viewcache.world_surfacevisible)
3973 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3974 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3978 extern rtexture_t *loadingscreentexture;
3979 void gl_main_start(void)
3981 loadingscreentexture = NULL;
3982 r_texture_blanknormalmap = NULL;
3983 r_texture_white = NULL;
3984 r_texture_grey128 = NULL;
3985 r_texture_black = NULL;
3986 r_texture_whitecube = NULL;
3987 r_texture_normalizationcube = NULL;
3988 r_texture_fogattenuation = NULL;
3989 r_texture_fogheighttexture = NULL;
3990 r_texture_gammaramps = NULL;
3991 r_texture_numcubemaps = 0;
3993 r_loaddds = r_texture_dds_load.integer != 0;
3994 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3996 switch(vid.renderpath)
3998 case RENDERPATH_GL20:
3999 case RENDERPATH_D3D9:
4000 case RENDERPATH_D3D10:
4001 case RENDERPATH_D3D11:
4002 case RENDERPATH_SOFT:
4003 case RENDERPATH_GLES2:
4004 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4005 Cvar_SetValueQuick(&gl_combine, 1);
4006 Cvar_SetValueQuick(&r_glsl, 1);
4007 r_loadnormalmap = true;
4011 case RENDERPATH_GL13:
4012 case RENDERPATH_GLES1:
4013 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4014 Cvar_SetValueQuick(&gl_combine, 1);
4015 Cvar_SetValueQuick(&r_glsl, 0);
4016 r_loadnormalmap = false;
4017 r_loadgloss = false;
4020 case RENDERPATH_GL11:
4021 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4022 Cvar_SetValueQuick(&gl_combine, 0);
4023 Cvar_SetValueQuick(&r_glsl, 0);
4024 r_loadnormalmap = false;
4025 r_loadgloss = false;
4031 R_FrameData_Reset();
4035 memset(r_queries, 0, sizeof(r_queries));
4037 r_qwskincache = NULL;
4038 r_qwskincache_size = 0;
4040 // due to caching of texture_t references, the collision cache must be reset
4041 Collision_Cache_Reset(true);
4043 // set up r_skinframe loading system for textures
4044 memset(&r_skinframe, 0, sizeof(r_skinframe));
4045 r_skinframe.loadsequence = 1;
4046 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4048 r_main_texturepool = R_AllocTexturePool();
4049 R_BuildBlankTextures();
4051 if (vid.support.arb_texture_cube_map)
4054 R_BuildNormalizationCube();
4056 r_texture_fogattenuation = NULL;
4057 r_texture_fogheighttexture = NULL;
4058 r_texture_gammaramps = NULL;
4059 //r_texture_fogintensity = NULL;
4060 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4061 memset(&r_waterstate, 0, sizeof(r_waterstate));
4062 r_glsl_permutation = NULL;
4063 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4064 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4065 glslshaderstring = NULL;
4067 r_hlsl_permutation = NULL;
4068 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4069 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4071 hlslshaderstring = NULL;
4072 memset(&r_svbsp, 0, sizeof (r_svbsp));
4074 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4075 r_texture_numcubemaps = 0;
4077 r_refdef.fogmasktable_density = 0;
4080 void gl_main_shutdown(void)
4083 R_FrameData_Reset();
4085 R_Main_FreeViewCache();
4087 switch(vid.renderpath)
4089 case RENDERPATH_GL11:
4090 case RENDERPATH_GL13:
4091 case RENDERPATH_GL20:
4092 case RENDERPATH_GLES1:
4093 case RENDERPATH_GLES2:
4094 #ifdef GL_SAMPLES_PASSED_ARB
4096 qglDeleteQueriesARB(r_maxqueries, r_queries);
4099 case RENDERPATH_D3D9:
4100 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4102 case RENDERPATH_D3D10:
4103 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4105 case RENDERPATH_D3D11:
4106 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4108 case RENDERPATH_SOFT:
4114 memset(r_queries, 0, sizeof(r_queries));
4116 r_qwskincache = NULL;
4117 r_qwskincache_size = 0;
4119 // clear out the r_skinframe state
4120 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4121 memset(&r_skinframe, 0, sizeof(r_skinframe));
4124 Mem_Free(r_svbsp.nodes);
4125 memset(&r_svbsp, 0, sizeof (r_svbsp));
4126 R_FreeTexturePool(&r_main_texturepool);
4127 loadingscreentexture = NULL;
4128 r_texture_blanknormalmap = NULL;
4129 r_texture_white = NULL;
4130 r_texture_grey128 = NULL;
4131 r_texture_black = NULL;
4132 r_texture_whitecube = NULL;
4133 r_texture_normalizationcube = NULL;
4134 r_texture_fogattenuation = NULL;
4135 r_texture_fogheighttexture = NULL;
4136 r_texture_gammaramps = NULL;
4137 r_texture_numcubemaps = 0;
4138 //r_texture_fogintensity = NULL;
4139 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4140 memset(&r_waterstate, 0, sizeof(r_waterstate));
4143 r_glsl_permutation = NULL;
4144 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4145 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4146 glslshaderstring = NULL;
4148 r_hlsl_permutation = NULL;
4149 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4150 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4152 hlslshaderstring = NULL;
4155 extern void CL_ParseEntityLump(char *entitystring);
4156 void gl_main_newmap(void)
4158 // FIXME: move this code to client
4159 char *entities, entname[MAX_QPATH];
4161 Mem_Free(r_qwskincache);
4162 r_qwskincache = NULL;
4163 r_qwskincache_size = 0;
4166 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4167 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4169 CL_ParseEntityLump(entities);
4173 if (cl.worldmodel->brush.entities)
4174 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4176 R_Main_FreeViewCache();
4178 R_FrameData_Reset();
4181 void GL_Main_Init(void)
4183 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4185 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4186 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4187 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4188 if (gamemode == GAME_NEHAHRA)
4190 Cvar_RegisterVariable (&gl_fogenable);
4191 Cvar_RegisterVariable (&gl_fogdensity);
4192 Cvar_RegisterVariable (&gl_fogred);
4193 Cvar_RegisterVariable (&gl_foggreen);
4194 Cvar_RegisterVariable (&gl_fogblue);
4195 Cvar_RegisterVariable (&gl_fogstart);
4196 Cvar_RegisterVariable (&gl_fogend);
4197 Cvar_RegisterVariable (&gl_skyclip);
4199 Cvar_RegisterVariable(&r_motionblur);
4200 Cvar_RegisterVariable(&r_damageblur);
4201 Cvar_RegisterVariable(&r_motionblur_averaging);
4202 Cvar_RegisterVariable(&r_motionblur_randomize);
4203 Cvar_RegisterVariable(&r_motionblur_minblur);
4204 Cvar_RegisterVariable(&r_motionblur_maxblur);
4205 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4206 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4207 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4208 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4209 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4210 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4211 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4212 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4213 Cvar_RegisterVariable(&r_equalize_entities_by);
4214 Cvar_RegisterVariable(&r_equalize_entities_to);
4215 Cvar_RegisterVariable(&r_depthfirst);
4216 Cvar_RegisterVariable(&r_useinfinitefarclip);
4217 Cvar_RegisterVariable(&r_farclip_base);
4218 Cvar_RegisterVariable(&r_farclip_world);
4219 Cvar_RegisterVariable(&r_nearclip);
4220 Cvar_RegisterVariable(&r_deformvertexes);
4221 Cvar_RegisterVariable(&r_transparent);
4222 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4223 Cvar_RegisterVariable(&r_showoverdraw);
4224 Cvar_RegisterVariable(&r_showbboxes);
4225 Cvar_RegisterVariable(&r_showsurfaces);
4226 Cvar_RegisterVariable(&r_showtris);
4227 Cvar_RegisterVariable(&r_shownormals);
4228 Cvar_RegisterVariable(&r_showlighting);
4229 Cvar_RegisterVariable(&r_showshadowvolumes);
4230 Cvar_RegisterVariable(&r_showcollisionbrushes);
4231 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4232 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4233 Cvar_RegisterVariable(&r_showdisabledepthtest);
4234 Cvar_RegisterVariable(&r_drawportals);
4235 Cvar_RegisterVariable(&r_drawentities);
4236 Cvar_RegisterVariable(&r_draw2d);
4237 Cvar_RegisterVariable(&r_drawworld);
4238 Cvar_RegisterVariable(&r_cullentities_trace);
4239 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4240 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4241 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4242 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4243 Cvar_RegisterVariable(&r_sortentities);
4244 Cvar_RegisterVariable(&r_drawviewmodel);
4245 Cvar_RegisterVariable(&r_drawexteriormodel);
4246 Cvar_RegisterVariable(&r_speeds);
4247 Cvar_RegisterVariable(&r_fullbrights);
4248 Cvar_RegisterVariable(&r_wateralpha);
4249 Cvar_RegisterVariable(&r_dynamic);
4250 Cvar_RegisterVariable(&r_fakelight);
4251 Cvar_RegisterVariable(&r_fakelight_intensity);
4252 Cvar_RegisterVariable(&r_fullbright);
4253 Cvar_RegisterVariable(&r_shadows);
4254 Cvar_RegisterVariable(&r_shadows_darken);
4255 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4256 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4257 Cvar_RegisterVariable(&r_shadows_throwdistance);
4258 Cvar_RegisterVariable(&r_shadows_throwdirection);
4259 Cvar_RegisterVariable(&r_shadows_focus);
4260 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4261 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4262 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4263 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4264 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4265 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4266 Cvar_RegisterVariable(&r_fog_exp2);
4267 Cvar_RegisterVariable(&r_fog_clear);
4268 Cvar_RegisterVariable(&r_drawfog);
4269 Cvar_RegisterVariable(&r_transparentdepthmasking);
4270 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4271 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4272 Cvar_RegisterVariable(&r_texture_dds_load);
4273 Cvar_RegisterVariable(&r_texture_dds_save);
4274 Cvar_RegisterVariable(&r_textureunits);
4275 Cvar_RegisterVariable(&gl_combine);
4276 Cvar_RegisterVariable(&r_viewfbo);
4277 Cvar_RegisterVariable(&r_viewscale);
4278 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4279 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4280 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4281 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4282 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4283 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4284 Cvar_RegisterVariable(&r_glsl);
4285 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4286 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4287 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4288 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4289 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4290 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4291 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4292 Cvar_RegisterVariable(&r_glsl_postprocess);
4293 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4294 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4295 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4296 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4297 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4298 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4299 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4300 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4302 Cvar_RegisterVariable(&r_water);
4303 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4304 Cvar_RegisterVariable(&r_water_clippingplanebias);
4305 Cvar_RegisterVariable(&r_water_refractdistort);
4306 Cvar_RegisterVariable(&r_water_reflectdistort);
4307 Cvar_RegisterVariable(&r_water_scissormode);
4308 Cvar_RegisterVariable(&r_water_lowquality);
4310 Cvar_RegisterVariable(&r_lerpsprites);
4311 Cvar_RegisterVariable(&r_lerpmodels);
4312 Cvar_RegisterVariable(&r_lerplightstyles);
4313 Cvar_RegisterVariable(&r_waterscroll);
4314 Cvar_RegisterVariable(&r_bloom);
4315 Cvar_RegisterVariable(&r_bloom_colorscale);
4316 Cvar_RegisterVariable(&r_bloom_brighten);
4317 Cvar_RegisterVariable(&r_bloom_blur);
4318 Cvar_RegisterVariable(&r_bloom_resolution);
4319 Cvar_RegisterVariable(&r_bloom_colorexponent);
4320 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4321 Cvar_RegisterVariable(&r_hdr);
4322 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4323 Cvar_RegisterVariable(&r_hdr_glowintensity);
4324 Cvar_RegisterVariable(&r_hdr_range);
4325 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4326 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4327 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4328 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4329 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4330 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4331 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4332 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4333 Cvar_RegisterVariable(&developer_texturelogging);
4334 Cvar_RegisterVariable(&gl_lightmaps);
4335 Cvar_RegisterVariable(&r_test);
4336 Cvar_RegisterVariable(&r_glsl_saturation);
4337 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4338 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4339 Cvar_RegisterVariable(&r_framedatasize);
4340 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4341 Cvar_SetValue("r_fullbrights", 0);
4342 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4345 extern void R_Textures_Init(void);
4346 extern void GL_Draw_Init(void);
4347 extern void GL_Main_Init(void);
4348 extern void R_Shadow_Init(void);
4349 extern void R_Sky_Init(void);
4350 extern void GL_Surf_Init(void);
4351 extern void R_Particles_Init(void);
4352 extern void R_Explosion_Init(void);
4353 extern void gl_backend_init(void);
4354 extern void Sbar_Init(void);
4355 extern void R_LightningBeams_Init(void);
4356 extern void Mod_RenderInit(void);
4357 extern void Font_Init(void);
4359 void Render_Init(void)
4372 R_LightningBeams_Init();
4382 extern char *ENGINE_EXTENSIONS;
4385 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4386 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4387 gl_version = (const char *)qglGetString(GL_VERSION);
4388 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4392 if (!gl_platformextensions)
4393 gl_platformextensions = "";
4395 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4396 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4397 Con_Printf("GL_VERSION: %s\n", gl_version);
4398 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4399 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4401 VID_CheckExtensions();
4403 // LordHavoc: report supported extensions
4404 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4406 // clear to black (loading plaque will be seen over this)
4407 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4411 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4415 if (r_trippy.integer)
4417 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4419 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4422 p = r_refdef.view.frustum + i;
4427 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4431 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4435 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4439 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4443 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4447 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4451 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4455 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4463 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4467 if (r_trippy.integer)
4469 for (i = 0;i < numplanes;i++)
4476 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4480 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4484 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4488 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4492 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4496 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4500 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4504 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4512 //==================================================================================
4514 // LordHavoc: this stores temporary data used within the same frame
4516 typedef struct r_framedata_mem_s
4518 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4519 size_t size; // how much usable space
4520 size_t current; // how much space in use
4521 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4522 size_t wantedsize; // how much space was allocated
4523 unsigned char *data; // start of real data (16byte aligned)
4527 static r_framedata_mem_t *r_framedata_mem;
4529 void R_FrameData_Reset(void)
4531 while (r_framedata_mem)
4533 r_framedata_mem_t *next = r_framedata_mem->purge;
4534 Mem_Free(r_framedata_mem);
4535 r_framedata_mem = next;
4539 void R_FrameData_Resize(void)
4542 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4543 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4544 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4546 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4547 newmem->wantedsize = wantedsize;
4548 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4549 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4550 newmem->current = 0;
4552 newmem->purge = r_framedata_mem;
4553 r_framedata_mem = newmem;
4557 void R_FrameData_NewFrame(void)
4559 R_FrameData_Resize();
4560 if (!r_framedata_mem)
4562 // if we ran out of space on the last frame, free the old memory now
4563 while (r_framedata_mem->purge)
4565 // repeatedly remove the second item in the list, leaving only head
4566 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4567 Mem_Free(r_framedata_mem->purge);
4568 r_framedata_mem->purge = next;
4570 // reset the current mem pointer
4571 r_framedata_mem->current = 0;
4572 r_framedata_mem->mark = 0;
4575 void *R_FrameData_Alloc(size_t size)
4579 // align to 16 byte boundary - the data pointer is already aligned, so we
4580 // only need to ensure the size of every allocation is also aligned
4581 size = (size + 15) & ~15;
4583 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4585 // emergency - we ran out of space, allocate more memory
4586 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4587 R_FrameData_Resize();
4590 data = r_framedata_mem->data + r_framedata_mem->current;
4591 r_framedata_mem->current += size;
4593 // count the usage for stats
4594 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4595 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4597 return (void *)data;
4600 void *R_FrameData_Store(size_t size, void *data)
4602 void *d = R_FrameData_Alloc(size);
4604 memcpy(d, data, size);
4608 void R_FrameData_SetMark(void)
4610 if (!r_framedata_mem)
4612 r_framedata_mem->mark = r_framedata_mem->current;
4615 void R_FrameData_ReturnToMark(void)
4617 if (!r_framedata_mem)
4619 r_framedata_mem->current = r_framedata_mem->mark;
4622 //==================================================================================
4624 // LordHavoc: animcache originally written by Echon, rewritten since then
4627 * Animation cache prevents re-generating mesh data for an animated model
4628 * multiple times in one frame for lighting, shadowing, reflections, etc.
4631 void R_AnimCache_Free(void)
4635 void R_AnimCache_ClearCache(void)
4638 entity_render_t *ent;
4640 for (i = 0;i < r_refdef.scene.numentities;i++)
4642 ent = r_refdef.scene.entities[i];
4643 ent->animcache_vertex3f = NULL;
4644 ent->animcache_normal3f = NULL;
4645 ent->animcache_svector3f = NULL;
4646 ent->animcache_tvector3f = NULL;
4647 ent->animcache_vertexmesh = NULL;
4648 ent->animcache_vertex3fbuffer = NULL;
4649 ent->animcache_vertexmeshbuffer = NULL;
4653 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4657 // check if we need the meshbuffers
4658 if (!vid.useinterleavedarrays)
4661 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4662 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4663 // TODO: upload vertex3f buffer?
4664 if (ent->animcache_vertexmesh)
4666 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4667 for (i = 0;i < numvertices;i++)
4668 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4669 if (ent->animcache_svector3f)
4670 for (i = 0;i < numvertices;i++)
4671 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4672 if (ent->animcache_tvector3f)
4673 for (i = 0;i < numvertices;i++)
4674 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4675 if (ent->animcache_normal3f)
4676 for (i = 0;i < numvertices;i++)
4677 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4678 // TODO: upload vertexmeshbuffer?
4682 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4684 dp_model_t *model = ent->model;
4686 // see if it's already cached this frame
4687 if (ent->animcache_vertex3f)
4689 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4690 if (wantnormals || wanttangents)
4692 if (ent->animcache_normal3f)
4693 wantnormals = false;
4694 if (ent->animcache_svector3f)
4695 wanttangents = false;
4696 if (wantnormals || wanttangents)
4698 numvertices = model->surfmesh.num_vertices;
4700 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4703 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4704 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4706 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4707 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4713 // see if this ent is worth caching
4714 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4716 // get some memory for this entity and generate mesh data
4717 numvertices = model->surfmesh.num_vertices;
4718 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4720 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4723 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4724 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4726 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4727 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4732 void R_AnimCache_CacheVisibleEntities(void)
4735 qboolean wantnormals = true;
4736 qboolean wanttangents = !r_showsurfaces.integer;
4738 switch(vid.renderpath)
4740 case RENDERPATH_GL20:
4741 case RENDERPATH_D3D9:
4742 case RENDERPATH_D3D10:
4743 case RENDERPATH_D3D11:
4744 case RENDERPATH_GLES2:
4746 case RENDERPATH_GL11:
4747 case RENDERPATH_GL13:
4748 case RENDERPATH_GLES1:
4749 wanttangents = false;
4751 case RENDERPATH_SOFT:
4755 if (r_shownormals.integer)
4756 wanttangents = wantnormals = true;
4758 // TODO: thread this
4759 // NOTE: R_PrepareRTLights() also caches entities
4761 for (i = 0;i < r_refdef.scene.numentities;i++)
4762 if (r_refdef.viewcache.entityvisible[i])
4763 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4766 //==================================================================================
4768 extern cvar_t r_overheadsprites_pushback;
4770 static void R_View_UpdateEntityLighting (void)
4773 entity_render_t *ent;
4774 vec3_t tempdiffusenormal, avg;
4775 vec_t f, fa, fd, fdd;
4776 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4778 for (i = 0;i < r_refdef.scene.numentities;i++)
4780 ent = r_refdef.scene.entities[i];
4782 // skip unseen models
4783 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4787 if (ent->model && ent->model->brush.num_leafs)
4789 // TODO: use modellight for r_ambient settings on world?
4790 VectorSet(ent->modellight_ambient, 0, 0, 0);
4791 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4792 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4796 // fetch the lighting from the worldmodel data
4797 VectorClear(ent->modellight_ambient);
4798 VectorClear(ent->modellight_diffuse);
4799 VectorClear(tempdiffusenormal);
4800 if (ent->flags & RENDER_LIGHT)
4803 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4805 // complete lightning for lit sprites
4806 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4807 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4809 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4810 org[2] = org[2] + r_overheadsprites_pushback.value;
4811 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4814 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4816 if(ent->flags & RENDER_EQUALIZE)
4818 // first fix up ambient lighting...
4819 if(r_equalize_entities_minambient.value > 0)
4821 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4824 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4825 if(fa < r_equalize_entities_minambient.value * fd)
4828 // fa'/fd' = minambient
4829 // fa'+0.25*fd' = fa+0.25*fd
4831 // fa' = fd' * minambient
4832 // fd'*(0.25+minambient) = fa+0.25*fd
4834 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4835 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4837 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4838 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
4839 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4840 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4845 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4847 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4848 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4852 // adjust brightness and saturation to target
4853 avg[0] = avg[1] = avg[2] = fa / f;
4854 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4855 avg[0] = avg[1] = avg[2] = fd / f;
4856 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4862 VectorSet(ent->modellight_ambient, 1, 1, 1);
4864 // move the light direction into modelspace coordinates for lighting code
4865 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4866 if(VectorLength2(ent->modellight_lightdir) == 0)
4867 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4868 VectorNormalize(ent->modellight_lightdir);
4872 #define MAX_LINEOFSIGHTTRACES 64
4874 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4877 vec3_t boxmins, boxmaxs;
4880 dp_model_t *model = r_refdef.scene.worldmodel;
4882 if (!model || !model->brush.TraceLineOfSight)
4885 // expand the box a little
4886 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4887 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4888 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4889 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4890 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4891 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4893 // return true if eye is inside enlarged box
4894 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4898 VectorCopy(eye, start);
4899 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4900 if (model->brush.TraceLineOfSight(model, start, end))
4903 // try various random positions
4904 for (i = 0;i < numsamples;i++)
4906 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4907 if (model->brush.TraceLineOfSight(model, start, end))
4915 static void R_View_UpdateEntityVisible (void)
4920 entity_render_t *ent;
4922 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4923 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4924 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4925 : RENDER_EXTERIORMODEL;
4926 if (!r_drawviewmodel.integer)
4927 renderimask |= RENDER_VIEWMODEL;
4928 if (!r_drawexteriormodel.integer)
4929 renderimask |= RENDER_EXTERIORMODEL;
4930 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4932 // worldmodel can check visibility
4933 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4934 for (i = 0;i < r_refdef.scene.numentities;i++)
4936 ent = r_refdef.scene.entities[i];
4937 if (!(ent->flags & renderimask))
4938 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)))
4939 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))
4940 r_refdef.viewcache.entityvisible[i] = true;
4945 // no worldmodel or it can't check visibility
4946 for (i = 0;i < r_refdef.scene.numentities;i++)
4948 ent = r_refdef.scene.entities[i];
4949 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));
4952 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4953 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4955 for (i = 0;i < r_refdef.scene.numentities;i++)
4957 if (!r_refdef.viewcache.entityvisible[i])
4959 ent = r_refdef.scene.entities[i];
4960 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4962 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4964 continue; // temp entities do pvs only
4965 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4966 ent->last_trace_visibility = realtime;
4967 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4968 r_refdef.viewcache.entityvisible[i] = 0;
4974 /// only used if skyrendermasked, and normally returns false
4975 int R_DrawBrushModelsSky (void)
4978 entity_render_t *ent;
4981 for (i = 0;i < r_refdef.scene.numentities;i++)
4983 if (!r_refdef.viewcache.entityvisible[i])
4985 ent = r_refdef.scene.entities[i];
4986 if (!ent->model || !ent->model->DrawSky)
4988 ent->model->DrawSky(ent);
4994 static void R_DrawNoModel(entity_render_t *ent);
4995 static void R_DrawModels(void)
4998 entity_render_t *ent;
5000 for (i = 0;i < r_refdef.scene.numentities;i++)
5002 if (!r_refdef.viewcache.entityvisible[i])
5004 ent = r_refdef.scene.entities[i];
5005 r_refdef.stats.entities++;
5007 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5010 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5011 Con_Printf("R_DrawModels\n");
5012 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]);
5013 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);
5014 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);
5017 if (ent->model && ent->model->Draw != NULL)
5018 ent->model->Draw(ent);
5024 static void R_DrawModelsDepth(void)
5027 entity_render_t *ent;
5029 for (i = 0;i < r_refdef.scene.numentities;i++)
5031 if (!r_refdef.viewcache.entityvisible[i])
5033 ent = r_refdef.scene.entities[i];
5034 if (ent->model && ent->model->DrawDepth != NULL)
5035 ent->model->DrawDepth(ent);
5039 static void R_DrawModelsDebug(void)
5042 entity_render_t *ent;
5044 for (i = 0;i < r_refdef.scene.numentities;i++)
5046 if (!r_refdef.viewcache.entityvisible[i])
5048 ent = r_refdef.scene.entities[i];
5049 if (ent->model && ent->model->DrawDebug != NULL)
5050 ent->model->DrawDebug(ent);
5054 static void R_DrawModelsAddWaterPlanes(void)
5057 entity_render_t *ent;
5059 for (i = 0;i < r_refdef.scene.numentities;i++)
5061 if (!r_refdef.viewcache.entityvisible[i])
5063 ent = r_refdef.scene.entities[i];
5064 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5065 ent->model->DrawAddWaterPlanes(ent);
5069 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5071 if (r_hdr_irisadaptation.integer)
5075 vec3_t diffusenormal;
5079 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5080 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5081 brightness = max(0.0000001f, brightness);
5082 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5083 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5084 current = r_hdr_irisadaptation_value.value;
5086 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5087 else if (current > goal)
5088 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5089 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5090 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5092 else if (r_hdr_irisadaptation_value.value != 1.0f)
5093 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5096 static void R_View_SetFrustum(const int *scissor)
5099 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5100 vec3_t forward, left, up, origin, v;
5104 // flipped x coordinates (because x points left here)
5105 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5106 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5108 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5109 switch(vid.renderpath)
5111 case RENDERPATH_D3D9:
5112 case RENDERPATH_D3D10:
5113 case RENDERPATH_D3D11:
5114 // non-flipped y coordinates
5115 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5116 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5118 case RENDERPATH_SOFT:
5119 case RENDERPATH_GL11:
5120 case RENDERPATH_GL13:
5121 case RENDERPATH_GL20:
5122 case RENDERPATH_GLES1:
5123 case RENDERPATH_GLES2:
5124 // non-flipped y coordinates
5125 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5126 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5131 // we can't trust r_refdef.view.forward and friends in reflected scenes
5132 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5135 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5136 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5137 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5138 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5139 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5140 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5141 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5142 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5143 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5144 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5145 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5146 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5150 zNear = r_refdef.nearclip;
5151 nudge = 1.0 - 1.0 / (1<<23);
5152 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5153 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5154 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5155 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5156 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5157 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5158 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5159 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5165 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5166 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5167 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5168 r_refdef.view.frustum[0].dist = m[15] - m[12];
5170 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5171 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5172 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5173 r_refdef.view.frustum[1].dist = m[15] + m[12];
5175 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5176 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5177 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5178 r_refdef.view.frustum[2].dist = m[15] - m[13];
5180 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5181 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5182 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5183 r_refdef.view.frustum[3].dist = m[15] + m[13];
5185 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5186 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5187 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5188 r_refdef.view.frustum[4].dist = m[15] - m[14];
5190 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5191 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5192 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5193 r_refdef.view.frustum[5].dist = m[15] + m[14];
5196 if (r_refdef.view.useperspective)
5198 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5199 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]);
5200 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]);
5201 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]);
5202 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]);
5204 // then the normals from the corners relative to origin
5205 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5206 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5207 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5208 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5210 // in a NORMAL view, forward cross left == up
5211 // in a REFLECTED view, forward cross left == down
5212 // so our cross products above need to be adjusted for a left handed coordinate system
5213 CrossProduct(forward, left, v);
5214 if(DotProduct(v, up) < 0)
5216 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5217 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5218 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5219 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5222 // Leaving those out was a mistake, those were in the old code, and they
5223 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5224 // I couldn't reproduce it after adding those normalizations. --blub
5225 VectorNormalize(r_refdef.view.frustum[0].normal);
5226 VectorNormalize(r_refdef.view.frustum[1].normal);
5227 VectorNormalize(r_refdef.view.frustum[2].normal);
5228 VectorNormalize(r_refdef.view.frustum[3].normal);
5230 // make the corners absolute
5231 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5232 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5233 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5234 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5237 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5239 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5240 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5241 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5242 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5243 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5247 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5248 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5249 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5250 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5251 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5252 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5253 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5254 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5255 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5256 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5258 r_refdef.view.numfrustumplanes = 5;
5260 if (r_refdef.view.useclipplane)
5262 r_refdef.view.numfrustumplanes = 6;
5263 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5266 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5267 PlaneClassify(r_refdef.view.frustum + i);
5269 // LordHavoc: note to all quake engine coders, Quake had a special case
5270 // for 90 degrees which assumed a square view (wrong), so I removed it,
5271 // Quake2 has it disabled as well.
5273 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5274 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5275 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5276 //PlaneClassify(&frustum[0]);
5278 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5279 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5280 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5281 //PlaneClassify(&frustum[1]);
5283 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5284 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5285 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5286 //PlaneClassify(&frustum[2]);
5288 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5289 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5290 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5291 //PlaneClassify(&frustum[3]);
5294 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5295 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5296 //PlaneClassify(&frustum[4]);
5299 void R_View_UpdateWithScissor(const int *myscissor)
5301 R_Main_ResizeViewCache();
5302 R_View_SetFrustum(myscissor);
5303 R_View_WorldVisibility(r_refdef.view.useclipplane);
5304 R_View_UpdateEntityVisible();
5305 R_View_UpdateEntityLighting();
5308 void R_View_Update(void)
5310 R_Main_ResizeViewCache();
5311 R_View_SetFrustum(NULL);
5312 R_View_WorldVisibility(r_refdef.view.useclipplane);
5313 R_View_UpdateEntityVisible();
5314 R_View_UpdateEntityLighting();
5317 float viewscalefpsadjusted = 1.0f;
5319 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5321 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5322 scale = bound(0.03125f, scale, 1.0f);
5323 *outwidth = (int)ceil(width * scale);
5324 *outheight = (int)ceil(height * scale);
5327 void R_Mesh_SetMainRenderTargets(void)
5329 if (r_bloomstate.fbo_framebuffer)
5330 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5332 R_Mesh_ResetRenderTargets();
5335 void R_SetupView(qboolean allowwaterclippingplane)
5337 const float *customclipplane = NULL;
5339 int scaledwidth, scaledheight;
5340 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5342 // LordHavoc: couldn't figure out how to make this approach the
5343 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5344 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5345 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5346 dist = r_refdef.view.clipplane.dist;
5347 plane[0] = r_refdef.view.clipplane.normal[0];
5348 plane[1] = r_refdef.view.clipplane.normal[1];
5349 plane[2] = r_refdef.view.clipplane.normal[2];
5351 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5354 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5355 if (!r_refdef.view.useperspective)
5356 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);
5357 else if (vid.stencil && r_useinfinitefarclip.integer)
5358 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);
5360 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);
5361 R_Mesh_SetMainRenderTargets();
5362 R_SetViewport(&r_refdef.view.viewport);
5363 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5365 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5366 float screenplane[4];
5367 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5368 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5369 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5370 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5371 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5375 void R_EntityMatrix(const matrix4x4_t *matrix)
5377 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5379 gl_modelmatrixchanged = false;
5380 gl_modelmatrix = *matrix;
5381 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5382 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5383 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5384 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5386 switch(vid.renderpath)
5388 case RENDERPATH_D3D9:
5390 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5391 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5394 case RENDERPATH_D3D10:
5395 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5397 case RENDERPATH_D3D11:
5398 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5400 case RENDERPATH_GL11:
5401 case RENDERPATH_GL13:
5402 case RENDERPATH_GLES1:
5403 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5405 case RENDERPATH_SOFT:
5406 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5407 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5409 case RENDERPATH_GL20:
5410 case RENDERPATH_GLES2:
5411 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5412 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5418 void R_ResetViewRendering2D(void)
5420 r_viewport_t viewport;
5423 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5424 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);
5425 R_Mesh_ResetRenderTargets();
5426 R_SetViewport(&viewport);
5427 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5428 GL_Color(1, 1, 1, 1);
5429 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5430 GL_BlendFunc(GL_ONE, GL_ZERO);
5431 GL_ScissorTest(false);
5432 GL_DepthMask(false);
5433 GL_DepthRange(0, 1);
5434 GL_DepthTest(false);
5435 GL_DepthFunc(GL_LEQUAL);
5436 R_EntityMatrix(&identitymatrix);
5437 R_Mesh_ResetTextureState();
5438 GL_PolygonOffset(0, 0);
5439 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5440 switch(vid.renderpath)
5442 case RENDERPATH_GL11:
5443 case RENDERPATH_GL13:
5444 case RENDERPATH_GL20:
5445 case RENDERPATH_GLES1:
5446 case RENDERPATH_GLES2:
5447 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5449 case RENDERPATH_D3D9:
5450 case RENDERPATH_D3D10:
5451 case RENDERPATH_D3D11:
5452 case RENDERPATH_SOFT:
5455 GL_CullFace(GL_NONE);
5458 void R_ResetViewRendering3D(void)
5463 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5464 GL_Color(1, 1, 1, 1);
5465 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5466 GL_BlendFunc(GL_ONE, GL_ZERO);
5467 GL_ScissorTest(true);
5469 GL_DepthRange(0, 1);
5471 GL_DepthFunc(GL_LEQUAL);
5472 R_EntityMatrix(&identitymatrix);
5473 R_Mesh_ResetTextureState();
5474 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5475 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5476 switch(vid.renderpath)
5478 case RENDERPATH_GL11:
5479 case RENDERPATH_GL13:
5480 case RENDERPATH_GL20:
5481 case RENDERPATH_GLES1:
5482 case RENDERPATH_GLES2:
5483 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5485 case RENDERPATH_D3D9:
5486 case RENDERPATH_D3D10:
5487 case RENDERPATH_D3D11:
5488 case RENDERPATH_SOFT:
5491 GL_CullFace(r_refdef.view.cullface_back);
5496 R_RenderView_UpdateViewVectors
5499 static void R_RenderView_UpdateViewVectors(void)
5501 // break apart the view matrix into vectors for various purposes
5502 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5503 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5504 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5505 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5506 // make an inverted copy of the view matrix for tracking sprites
5507 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5510 void R_RenderScene(void);
5511 void R_RenderWaterPlanes(void);
5513 static void R_Water_StartFrame(void)
5516 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5517 r_waterstate_waterplane_t *p;
5519 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5522 switch(vid.renderpath)
5524 case RENDERPATH_GL20:
5525 case RENDERPATH_D3D9:
5526 case RENDERPATH_D3D10:
5527 case RENDERPATH_D3D11:
5528 case RENDERPATH_SOFT:
5529 case RENDERPATH_GLES2:
5531 case RENDERPATH_GL11:
5532 case RENDERPATH_GL13:
5533 case RENDERPATH_GLES1:
5537 // set waterwidth and waterheight to the water resolution that will be
5538 // used (often less than the screen resolution for faster rendering)
5539 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5541 // calculate desired texture sizes
5542 // can't use water if the card does not support the texture size
5543 if (!r_water.integer || r_showsurfaces.integer)
5544 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5545 else if (vid.support.arb_texture_non_power_of_two)
5547 texturewidth = waterwidth;
5548 textureheight = waterheight;
5549 camerawidth = waterwidth;
5550 cameraheight = waterheight;
5554 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5555 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5556 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5557 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5560 // allocate textures as needed
5561 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5563 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5564 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5566 if (p->texture_refraction)
5567 R_FreeTexture(p->texture_refraction);
5568 p->texture_refraction = NULL;
5569 if (p->texture_reflection)
5570 R_FreeTexture(p->texture_reflection);
5571 p->texture_reflection = NULL;
5572 if (p->texture_camera)
5573 R_FreeTexture(p->texture_camera);
5574 p->texture_camera = NULL;
5576 memset(&r_waterstate, 0, sizeof(r_waterstate));
5577 r_waterstate.texturewidth = texturewidth;
5578 r_waterstate.textureheight = textureheight;
5579 r_waterstate.camerawidth = camerawidth;
5580 r_waterstate.cameraheight = cameraheight;
5583 if (r_waterstate.texturewidth)
5585 int scaledwidth, scaledheight;
5587 r_waterstate.enabled = true;
5589 // when doing a reduced render (HDR) we want to use a smaller area
5590 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5591 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5592 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5594 // set up variables that will be used in shader setup
5595 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5596 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5597 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5598 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5601 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5602 r_waterstate.numwaterplanes = 0;
5605 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5607 int triangleindex, planeindex;
5613 r_waterstate_waterplane_t *p;
5614 texture_t *t = R_GetCurrentTexture(surface->texture);
5616 // just use the first triangle with a valid normal for any decisions
5617 VectorClear(normal);
5618 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5620 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5621 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5622 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5623 TriangleNormal(vert[0], vert[1], vert[2], normal);
5624 if (VectorLength2(normal) >= 0.001)
5628 VectorCopy(normal, plane.normal);
5629 VectorNormalize(plane.normal);
5630 plane.dist = DotProduct(vert[0], plane.normal);
5631 PlaneClassify(&plane);
5632 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5634 // skip backfaces (except if nocullface is set)
5635 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5637 VectorNegate(plane.normal, plane.normal);
5639 PlaneClassify(&plane);
5643 // find a matching plane if there is one
5644 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5645 if(p->camera_entity == t->camera_entity)
5646 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5648 if (planeindex >= r_waterstate.maxwaterplanes)
5649 return; // nothing we can do, out of planes
5651 // if this triangle does not fit any known plane rendered this frame, add one
5652 if (planeindex >= r_waterstate.numwaterplanes)
5654 // store the new plane
5655 r_waterstate.numwaterplanes++;
5657 // clear materialflags and pvs
5658 p->materialflags = 0;
5659 p->pvsvalid = false;
5660 p->camera_entity = t->camera_entity;
5661 VectorCopy(surface->mins, p->mins);
5662 VectorCopy(surface->maxs, p->maxs);
5667 p->mins[0] = min(p->mins[0], surface->mins[0]);
5668 p->mins[1] = min(p->mins[1], surface->mins[1]);
5669 p->mins[2] = min(p->mins[2], surface->mins[2]);
5670 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5671 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5672 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5674 // merge this surface's materialflags into the waterplane
5675 p->materialflags |= t->currentmaterialflags;
5676 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5678 // merge this surface's PVS into the waterplane
5679 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5680 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5681 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5683 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5689 extern cvar_t r_drawparticles;
5690 extern cvar_t r_drawdecals;
5692 static void R_Water_ProcessPlanes(void)
5695 r_refdef_view_t originalview;
5696 r_refdef_view_t myview;
5697 int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5698 r_waterstate_waterplane_t *p;
5701 originalview = r_refdef.view;
5703 // lowquality hack, temporarily shut down some cvars and restore afterwards
5704 qualityreduction = r_water_lowquality.integer;
5705 if (qualityreduction > 0)
5707 if (qualityreduction >= 1)
5709 old_r_shadows = r_shadows.integer;
5710 old_r_worldrtlight = r_shadow_realtime_world.integer;
5711 old_r_dlight = r_shadow_realtime_dlight.integer;
5712 Cvar_SetValueQuick(&r_shadows, 0);
5713 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5714 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5716 if (qualityreduction >= 2)
5718 old_r_dynamic = r_dynamic.integer;
5719 old_r_particles = r_drawparticles.integer;
5720 old_r_decals = r_drawdecals.integer;
5721 Cvar_SetValueQuick(&r_dynamic, 0);
5722 Cvar_SetValueQuick(&r_drawparticles, 0);
5723 Cvar_SetValueQuick(&r_drawdecals, 0);
5727 // make sure enough textures are allocated
5728 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5730 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5732 if (!p->texture_refraction)
5733 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);
5734 if (!p->texture_refraction)
5737 else if (p->materialflags & MATERIALFLAG_CAMERA)
5739 if (!p->texture_camera)
5740 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);
5741 if (!p->texture_camera)
5745 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5747 if (!p->texture_reflection)
5748 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);
5749 if (!p->texture_reflection)
5755 r_refdef.view = originalview;
5756 r_refdef.view.showdebug = false;
5757 r_refdef.view.width = r_waterstate.waterwidth;
5758 r_refdef.view.height = r_waterstate.waterheight;
5759 r_refdef.view.useclipplane = true;
5760 myview = r_refdef.view;
5761 r_waterstate.renderingscene = true;
5762 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5764 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5766 r_refdef.view = myview;
5767 if(r_water_scissormode.integer)
5770 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5771 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5774 // render reflected scene and copy into texture
5775 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5776 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5777 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5778 r_refdef.view.clipplane = p->plane;
5779 // reverse the cullface settings for this render
5780 r_refdef.view.cullface_front = GL_FRONT;
5781 r_refdef.view.cullface_back = GL_BACK;
5782 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5784 r_refdef.view.usecustompvs = true;
5786 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5788 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5791 R_ResetViewRendering3D();
5792 R_ClearScreen(r_refdef.fogenabled);
5793 if(r_water_scissormode.integer & 2)
5794 R_View_UpdateWithScissor(myscissor);
5797 if(r_water_scissormode.integer & 1)
5798 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5801 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);
5804 // render the normal view scene and copy into texture
5805 // (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)
5806 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5808 r_refdef.view = myview;
5809 if(r_water_scissormode.integer)
5812 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5813 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5816 r_waterstate.renderingrefraction = true;
5818 r_refdef.view.clipplane = p->plane;
5819 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5820 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5822 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5824 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5825 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5826 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5827 R_RenderView_UpdateViewVectors();
5828 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5830 r_refdef.view.usecustompvs = true;
5831 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);
5835 PlaneClassify(&r_refdef.view.clipplane);
5837 R_ResetViewRendering3D();
5838 R_ClearScreen(r_refdef.fogenabled);
5839 if(r_water_scissormode.integer & 2)
5840 R_View_UpdateWithScissor(myscissor);
5843 if(r_water_scissormode.integer & 1)
5844 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5847 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);
5848 r_waterstate.renderingrefraction = false;
5850 else if (p->materialflags & MATERIALFLAG_CAMERA)
5852 r_refdef.view = myview;
5854 r_refdef.view.clipplane = p->plane;
5855 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5856 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5858 r_refdef.view.width = r_waterstate.camerawidth;
5859 r_refdef.view.height = r_waterstate.cameraheight;
5860 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5861 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5863 if(p->camera_entity)
5865 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5866 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5869 // note: all of the view is used for displaying... so
5870 // there is no use in scissoring
5872 // reverse the cullface settings for this render
5873 r_refdef.view.cullface_front = GL_FRONT;
5874 r_refdef.view.cullface_back = GL_BACK;
5875 // also reverse the view matrix
5876 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
5877 R_RenderView_UpdateViewVectors();
5878 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5880 r_refdef.view.usecustompvs = true;
5881 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);
5884 // camera needs no clipplane
5885 r_refdef.view.useclipplane = false;
5887 PlaneClassify(&r_refdef.view.clipplane);
5889 R_ResetViewRendering3D();
5890 R_ClearScreen(r_refdef.fogenabled);
5894 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);
5895 r_waterstate.renderingrefraction = false;
5899 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5900 r_waterstate.renderingscene = false;
5901 r_refdef.view = originalview;
5902 R_ResetViewRendering3D();
5903 R_ClearScreen(r_refdef.fogenabled);
5907 r_refdef.view = originalview;
5908 r_waterstate.renderingscene = false;
5909 Cvar_SetValueQuick(&r_water, 0);
5910 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5912 // lowquality hack, restore cvars
5913 if (qualityreduction > 0)
5915 if (qualityreduction >= 1)
5917 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5918 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5919 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5921 if (qualityreduction >= 2)
5923 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5924 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5925 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5930 void R_Bloom_StartFrame(void)
5932 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5933 int viewwidth, viewheight;
5936 if (r_viewscale_fpsscaling.integer)
5938 double actualframetime;
5939 double targetframetime;
5941 actualframetime = r_refdef.lastdrawscreentime;
5942 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5943 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5944 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5945 if (r_viewscale_fpsscaling_stepsize.value > 0)
5946 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5947 viewscalefpsadjusted += adjust;
5948 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5951 viewscalefpsadjusted = 1.0f;
5953 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5955 switch(vid.renderpath)
5957 case RENDERPATH_GL20:
5958 case RENDERPATH_D3D9:
5959 case RENDERPATH_D3D10:
5960 case RENDERPATH_D3D11:
5961 case RENDERPATH_SOFT:
5962 case RENDERPATH_GLES2:
5964 case RENDERPATH_GL11:
5965 case RENDERPATH_GL13:
5966 case RENDERPATH_GLES1:
5970 // set bloomwidth and bloomheight to the bloom resolution that will be
5971 // used (often less than the screen resolution for faster rendering)
5972 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5973 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5974 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5975 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5976 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5978 // calculate desired texture sizes
5979 if (vid.support.arb_texture_non_power_of_two)
5981 screentexturewidth = vid.width;
5982 screentextureheight = vid.height;
5983 bloomtexturewidth = r_bloomstate.bloomwidth;
5984 bloomtextureheight = r_bloomstate.bloomheight;
5988 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5989 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5990 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5991 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5994 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))
5996 Cvar_SetValueQuick(&r_hdr, 0);
5997 Cvar_SetValueQuick(&r_bloom, 0);
5998 Cvar_SetValueQuick(&r_motionblur, 0);
5999 Cvar_SetValueQuick(&r_damageblur, 0);
6002 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)
6003 screentexturewidth = screentextureheight = 0;
6004 if (!r_hdr.integer && !r_bloom.integer)
6005 bloomtexturewidth = bloomtextureheight = 0;
6007 textype = TEXTYPE_COLORBUFFER;
6008 switch (vid.renderpath)
6010 case RENDERPATH_GL20:
6011 case RENDERPATH_GLES2:
6012 if (vid.support.ext_framebuffer_object)
6014 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6015 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6018 case RENDERPATH_GL11:
6019 case RENDERPATH_GL13:
6020 case RENDERPATH_GLES1:
6021 case RENDERPATH_D3D9:
6022 case RENDERPATH_D3D10:
6023 case RENDERPATH_D3D11:
6024 case RENDERPATH_SOFT:
6028 // allocate textures as needed
6029 if (r_bloomstate.screentexturewidth != screentexturewidth
6030 || r_bloomstate.screentextureheight != screentextureheight
6031 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6032 || r_bloomstate.bloomtextureheight != bloomtextureheight
6033 || r_bloomstate.texturetype != textype
6034 || r_bloomstate.viewfbo != r_viewfbo.integer)
6036 if (r_bloomstate.texture_bloom)
6037 R_FreeTexture(r_bloomstate.texture_bloom);
6038 r_bloomstate.texture_bloom = NULL;
6039 if (r_bloomstate.texture_screen)
6040 R_FreeTexture(r_bloomstate.texture_screen);
6041 r_bloomstate.texture_screen = NULL;
6042 if (r_bloomstate.fbo_framebuffer)
6043 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6044 r_bloomstate.fbo_framebuffer = 0;
6045 if (r_bloomstate.texture_framebuffercolor)
6046 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6047 r_bloomstate.texture_framebuffercolor = NULL;
6048 if (r_bloomstate.texture_framebufferdepth)
6049 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6050 r_bloomstate.texture_framebufferdepth = NULL;
6051 r_bloomstate.screentexturewidth = screentexturewidth;
6052 r_bloomstate.screentextureheight = screentextureheight;
6053 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6054 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);
6055 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6057 // FIXME: choose depth bits based on a cvar
6058 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6059 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);
6060 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6061 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6063 // render depth into one texture and normalmap into the other
6067 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6068 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6069 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6070 if (status != GL_FRAMEBUFFER_COMPLETE)
6071 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6075 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6076 r_bloomstate.bloomtextureheight = bloomtextureheight;
6077 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6078 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);
6079 r_bloomstate.viewfbo = r_viewfbo.integer;
6080 r_bloomstate.texturetype = textype;
6083 // when doing a reduced render (HDR) we want to use a smaller area
6084 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6085 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6086 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6087 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6088 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6090 // set up a texcoord array for the full resolution screen image
6091 // (we have to keep this around to copy back during final render)
6092 r_bloomstate.screentexcoord2f[0] = 0;
6093 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6094 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6095 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6096 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6097 r_bloomstate.screentexcoord2f[5] = 0;
6098 r_bloomstate.screentexcoord2f[6] = 0;
6099 r_bloomstate.screentexcoord2f[7] = 0;
6101 // set up a texcoord array for the reduced resolution bloom image
6102 // (which will be additive blended over the screen image)
6103 r_bloomstate.bloomtexcoord2f[0] = 0;
6104 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6105 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6106 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6107 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6108 r_bloomstate.bloomtexcoord2f[5] = 0;
6109 r_bloomstate.bloomtexcoord2f[6] = 0;
6110 r_bloomstate.bloomtexcoord2f[7] = 0;
6112 switch(vid.renderpath)
6114 case RENDERPATH_GL11:
6115 case RENDERPATH_GL13:
6116 case RENDERPATH_GL20:
6117 case RENDERPATH_SOFT:
6118 case RENDERPATH_GLES1:
6119 case RENDERPATH_GLES2:
6121 case RENDERPATH_D3D9:
6122 case RENDERPATH_D3D10:
6123 case RENDERPATH_D3D11:
6126 for (i = 0;i < 4;i++)
6128 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6129 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6130 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6131 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6137 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6139 r_bloomstate.enabled = true;
6140 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6143 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);
6145 if (r_bloomstate.fbo_framebuffer)
6146 r_refdef.view.clear = true;
6149 void R_Bloom_CopyBloomTexture(float colorscale)
6151 r_refdef.stats.bloom++;
6153 // scale down screen texture to the bloom texture size
6155 R_Mesh_SetMainRenderTargets();
6156 R_SetViewport(&r_bloomstate.viewport);
6157 GL_BlendFunc(GL_ONE, GL_ZERO);
6158 GL_Color(colorscale, colorscale, colorscale, 1);
6159 // 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...
6160 switch(vid.renderpath)
6162 case RENDERPATH_GL11:
6163 case RENDERPATH_GL13:
6164 case RENDERPATH_GL20:
6165 case RENDERPATH_GLES1:
6166 case RENDERPATH_GLES2:
6167 case RENDERPATH_SOFT:
6168 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6170 case RENDERPATH_D3D9:
6171 case RENDERPATH_D3D10:
6172 case RENDERPATH_D3D11:
6173 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6176 // TODO: do boxfilter scale-down in shader?
6177 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6178 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6179 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6181 // we now have a bloom image in the framebuffer
6182 // copy it into the bloom image texture for later processing
6183 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);
6184 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6187 void R_Bloom_CopyHDRTexture(void)
6189 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);
6190 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6193 void R_Bloom_MakeTexture(void)
6196 float xoffset, yoffset, r, brighten;
6198 r_refdef.stats.bloom++;
6200 R_ResetViewRendering2D();
6202 // we have a bloom image in the framebuffer
6204 R_SetViewport(&r_bloomstate.viewport);
6206 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6209 r = bound(0, r_bloom_colorexponent.value / x, 1);
6210 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6212 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6213 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6214 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6215 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6217 // copy the vertically blurred bloom view to a texture
6218 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);
6219 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6222 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6223 brighten = r_bloom_brighten.value;
6224 if (r_bloomstate.hdr)
6225 brighten *= r_hdr_range.value;
6226 brighten = sqrt(brighten);
6228 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6229 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6231 for (dir = 0;dir < 2;dir++)
6233 // blend on at multiple vertical offsets to achieve a vertical blur
6234 // TODO: do offset blends using GLSL
6235 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6236 GL_BlendFunc(GL_ONE, GL_ZERO);
6237 for (x = -range;x <= range;x++)
6239 if (!dir){xoffset = 0;yoffset = x;}
6240 else {xoffset = x;yoffset = 0;}
6241 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6242 yoffset /= (float)r_bloomstate.bloomtextureheight;
6243 // compute a texcoord array with the specified x and y offset
6244 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6245 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6246 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6247 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6248 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6249 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6250 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6251 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6252 // this r value looks like a 'dot' particle, fading sharply to
6253 // black at the edges
6254 // (probably not realistic but looks good enough)
6255 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6256 //r = brighten/(range*2+1);
6257 r = brighten / (range * 2 + 1);
6259 r *= (1 - x*x/(float)(range*range));
6260 GL_Color(r, r, r, 1);
6261 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6262 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6263 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6264 GL_BlendFunc(GL_ONE, GL_ONE);
6267 // copy the vertically blurred bloom view to a texture
6268 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);
6269 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6273 void R_HDR_RenderBloomTexture(void)
6275 int oldwidth, oldheight;
6276 float oldcolorscale;
6277 qboolean oldwaterstate;
6279 oldwaterstate = r_waterstate.enabled;
6280 oldcolorscale = r_refdef.view.colorscale;
6281 oldwidth = r_refdef.view.width;
6282 oldheight = r_refdef.view.height;
6283 r_refdef.view.width = r_bloomstate.bloomwidth;
6284 r_refdef.view.height = r_bloomstate.bloomheight;
6286 if(r_hdr.integer < 2)
6287 r_waterstate.enabled = false;
6289 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6290 // TODO: add exposure compensation features
6291 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6293 r_refdef.view.showdebug = false;
6294 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6296 R_ResetViewRendering3D();
6298 R_ClearScreen(r_refdef.fogenabled);
6299 if (r_timereport_active)
6300 R_TimeReport("HDRclear");
6303 if (r_timereport_active)
6304 R_TimeReport("visibility");
6306 // only do secondary renders with HDR if r_hdr is 2 or higher
6307 r_waterstate.numwaterplanes = 0;
6308 if (r_waterstate.enabled)
6309 R_RenderWaterPlanes();
6311 r_refdef.view.showdebug = true;
6313 r_waterstate.numwaterplanes = 0;
6315 R_ResetViewRendering2D();
6317 R_Bloom_CopyHDRTexture();
6318 R_Bloom_MakeTexture();
6320 // restore the view settings
6321 r_waterstate.enabled = oldwaterstate;
6322 r_refdef.view.width = oldwidth;
6323 r_refdef.view.height = oldheight;
6324 r_refdef.view.colorscale = oldcolorscale;
6326 R_ResetViewRendering3D();
6328 R_ClearScreen(r_refdef.fogenabled);
6329 if (r_timereport_active)
6330 R_TimeReport("viewclear");
6333 static void R_BlendView(void)
6335 unsigned int permutation;
6336 float uservecs[4][4];
6338 switch (vid.renderpath)
6340 case RENDERPATH_GL20:
6341 case RENDERPATH_D3D9:
6342 case RENDERPATH_D3D10:
6343 case RENDERPATH_D3D11:
6344 case RENDERPATH_SOFT:
6345 case RENDERPATH_GLES2:
6347 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6348 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6349 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6350 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6351 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6353 if (r_bloomstate.texture_screen)
6355 // make sure the buffer is available
6356 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6358 R_ResetViewRendering2D();
6359 R_Mesh_SetMainRenderTargets();
6361 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6363 // declare variables
6364 float blur_factor, blur_mouseaccel, blur_velocity;
6365 static float blur_average;
6366 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6368 // set a goal for the factoring
6369 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6370 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6371 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6372 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6373 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6374 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6376 // from the goal, pick an averaged value between goal and last value
6377 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6378 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6380 // enforce minimum amount of blur
6381 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6383 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6385 // calculate values into a standard alpha
6386 cl.motionbluralpha = 1 - exp(-
6388 (r_motionblur.value * blur_factor / 80)
6390 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6393 max(0.0001, cl.time - cl.oldtime) // fps independent
6396 // randomization for the blur value to combat persistent ghosting
6397 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6398 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6401 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6403 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6404 GL_Color(1, 1, 1, cl.motionbluralpha);
6405 switch(vid.renderpath)
6407 case RENDERPATH_GL11:
6408 case RENDERPATH_GL13:
6409 case RENDERPATH_GL20:
6410 case RENDERPATH_GLES1:
6411 case RENDERPATH_GLES2:
6412 case RENDERPATH_SOFT:
6413 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6415 case RENDERPATH_D3D9:
6416 case RENDERPATH_D3D10:
6417 case RENDERPATH_D3D11:
6418 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6421 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6422 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6423 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6426 // updates old view angles for next pass
6427 VectorCopy(cl.viewangles, blur_oldangles);
6430 // copy view into the screen texture
6431 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);
6432 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6434 else if (!r_bloomstate.texture_bloom)
6436 // we may still have to do view tint...
6437 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6439 // apply a color tint to the whole view
6440 R_ResetViewRendering2D();
6441 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6442 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6443 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6444 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6445 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6447 break; // no screen processing, no bloom, skip it
6450 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6452 // render simple bloom effect
6453 // copy the screen and shrink it and darken it for the bloom process
6454 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6455 // make the bloom texture
6456 R_Bloom_MakeTexture();
6459 #if _MSC_VER >= 1400
6460 #define sscanf sscanf_s
6462 memset(uservecs, 0, sizeof(uservecs));
6463 if (r_glsl_postprocess_uservec1_enable.integer)
6464 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6465 if (r_glsl_postprocess_uservec2_enable.integer)
6466 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6467 if (r_glsl_postprocess_uservec3_enable.integer)
6468 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6469 if (r_glsl_postprocess_uservec4_enable.integer)
6470 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6472 R_ResetViewRendering2D();
6473 GL_Color(1, 1, 1, 1);
6474 GL_BlendFunc(GL_ONE, GL_ZERO);
6476 switch(vid.renderpath)
6478 case RENDERPATH_GL20:
6479 case RENDERPATH_GLES2:
6480 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6481 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6482 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6483 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6484 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6485 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]);
6486 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6487 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]);
6488 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]);
6489 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]);
6490 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]);
6491 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6492 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6493 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);
6495 case RENDERPATH_D3D9:
6497 // 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...
6498 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6499 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6500 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6501 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6502 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6503 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6504 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6505 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6506 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6507 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6508 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6509 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6510 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6511 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6514 case RENDERPATH_D3D10:
6515 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6517 case RENDERPATH_D3D11:
6518 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6520 case RENDERPATH_SOFT:
6521 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6522 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6523 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6524 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6525 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6526 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6527 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6528 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6529 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6530 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6531 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6532 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6533 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6534 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6539 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6540 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6542 case RENDERPATH_GL11:
6543 case RENDERPATH_GL13:
6544 case RENDERPATH_GLES1:
6545 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6547 // apply a color tint to the whole view
6548 R_ResetViewRendering2D();
6549 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6550 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6551 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6552 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6553 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6559 matrix4x4_t r_waterscrollmatrix;
6561 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6563 if (r_refdef.fog_density)
6565 r_refdef.fogcolor[0] = r_refdef.fog_red;
6566 r_refdef.fogcolor[1] = r_refdef.fog_green;
6567 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6569 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6570 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6571 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6572 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6576 VectorCopy(r_refdef.fogcolor, fogvec);
6577 // color.rgb *= ContrastBoost * SceneBrightness;
6578 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6579 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6580 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6581 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6586 void R_UpdateVariables(void)
6590 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6592 r_refdef.farclip = r_farclip_base.value;
6593 if (r_refdef.scene.worldmodel)
6594 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6595 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6597 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6598 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6599 r_refdef.polygonfactor = 0;
6600 r_refdef.polygonoffset = 0;
6601 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6602 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6604 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6605 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6606 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6607 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6608 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6609 if (FAKELIGHT_ENABLED)
6611 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6613 if (r_showsurfaces.integer)
6615 r_refdef.scene.rtworld = false;
6616 r_refdef.scene.rtworldshadows = false;
6617 r_refdef.scene.rtdlight = false;
6618 r_refdef.scene.rtdlightshadows = false;
6619 r_refdef.lightmapintensity = 0;
6622 if (gamemode == GAME_NEHAHRA)
6624 if (gl_fogenable.integer)
6626 r_refdef.oldgl_fogenable = true;
6627 r_refdef.fog_density = gl_fogdensity.value;
6628 r_refdef.fog_red = gl_fogred.value;
6629 r_refdef.fog_green = gl_foggreen.value;
6630 r_refdef.fog_blue = gl_fogblue.value;
6631 r_refdef.fog_alpha = 1;
6632 r_refdef.fog_start = 0;
6633 r_refdef.fog_end = gl_skyclip.value;
6634 r_refdef.fog_height = 1<<30;
6635 r_refdef.fog_fadedepth = 128;
6637 else if (r_refdef.oldgl_fogenable)
6639 r_refdef.oldgl_fogenable = false;
6640 r_refdef.fog_density = 0;
6641 r_refdef.fog_red = 0;
6642 r_refdef.fog_green = 0;
6643 r_refdef.fog_blue = 0;
6644 r_refdef.fog_alpha = 0;
6645 r_refdef.fog_start = 0;
6646 r_refdef.fog_end = 0;
6647 r_refdef.fog_height = 1<<30;
6648 r_refdef.fog_fadedepth = 128;
6652 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6653 r_refdef.fog_start = max(0, r_refdef.fog_start);
6654 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6656 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6658 if (r_refdef.fog_density && r_drawfog.integer)
6660 r_refdef.fogenabled = true;
6661 // this is the point where the fog reaches 0.9986 alpha, which we
6662 // consider a good enough cutoff point for the texture
6663 // (0.9986 * 256 == 255.6)
6664 if (r_fog_exp2.integer)
6665 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6667 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6668 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6669 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6670 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6671 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6672 R_BuildFogHeightTexture();
6673 // fog color was already set
6674 // update the fog texture
6675 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)
6676 R_BuildFogTexture();
6677 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6678 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6681 r_refdef.fogenabled = false;
6683 switch(vid.renderpath)
6685 case RENDERPATH_GL20:
6686 case RENDERPATH_D3D9:
6687 case RENDERPATH_D3D10:
6688 case RENDERPATH_D3D11:
6689 case RENDERPATH_SOFT:
6690 case RENDERPATH_GLES2:
6691 if(v_glslgamma.integer && !vid_gammatables_trivial)
6693 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6695 // build GLSL gamma texture
6696 #define RAMPWIDTH 256
6697 unsigned short ramp[RAMPWIDTH * 3];
6698 unsigned char rampbgr[RAMPWIDTH][4];
6701 r_texture_gammaramps_serial = vid_gammatables_serial;
6703 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6704 for(i = 0; i < RAMPWIDTH; ++i)
6706 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6707 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6708 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6711 if (r_texture_gammaramps)
6713 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6717 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6723 // remove GLSL gamma texture
6726 case RENDERPATH_GL11:
6727 case RENDERPATH_GL13:
6728 case RENDERPATH_GLES1:
6733 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6734 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6740 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6741 if( scenetype != r_currentscenetype ) {
6742 // store the old scenetype
6743 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6744 r_currentscenetype = scenetype;
6745 // move in the new scene
6746 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6755 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6757 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6758 if( scenetype == r_currentscenetype ) {
6759 return &r_refdef.scene;
6761 return &r_scenes_store[ scenetype ];
6765 int R_SortEntities_Compare(const void *ap, const void *bp)
6767 const entity_render_t *a = *(const entity_render_t **)ap;
6768 const entity_render_t *b = *(const entity_render_t **)bp;
6771 if(a->model < b->model)
6773 if(a->model > b->model)
6777 // TODO possibly calculate the REAL skinnum here first using
6779 if(a->skinnum < b->skinnum)
6781 if(a->skinnum > b->skinnum)
6784 // everything we compared is equal
6787 void R_SortEntities(void)
6789 // below or equal 2 ents, sorting never gains anything
6790 if(r_refdef.scene.numentities <= 2)
6793 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6801 int dpsoftrast_test;
6802 extern void R_Shadow_UpdateBounceGridTexture(void);
6803 extern cvar_t r_shadow_bouncegrid;
6804 void R_RenderView(void)
6806 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6808 dpsoftrast_test = r_test.integer;
6810 if (r_timereport_active)
6811 R_TimeReport("start");
6812 r_textureframe++; // used only by R_GetCurrentTexture
6813 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6815 if(R_CompileShader_CheckStaticParms())
6818 if (!r_drawentities.integer)
6819 r_refdef.scene.numentities = 0;
6820 else if (r_sortentities.integer)
6823 R_AnimCache_ClearCache();
6824 R_FrameData_NewFrame();
6826 /* adjust for stereo display */
6827 if(R_Stereo_Active())
6829 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);
6830 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6833 if (r_refdef.view.isoverlay)
6835 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6836 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6837 R_TimeReport("depthclear");
6839 r_refdef.view.showdebug = false;
6841 r_waterstate.enabled = false;
6842 r_waterstate.numwaterplanes = 0;
6846 r_refdef.view.matrix = originalmatrix;
6852 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6854 r_refdef.view.matrix = originalmatrix;
6855 return; //Host_Error ("R_RenderView: NULL worldmodel");
6858 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6860 R_RenderView_UpdateViewVectors();
6862 R_Shadow_UpdateWorldLightSelection();
6864 R_Bloom_StartFrame();
6865 R_Water_StartFrame();
6868 if (r_timereport_active)
6869 R_TimeReport("viewsetup");
6871 R_ResetViewRendering3D();
6873 if (r_refdef.view.clear || r_refdef.fogenabled)
6875 R_ClearScreen(r_refdef.fogenabled);
6876 if (r_timereport_active)
6877 R_TimeReport("viewclear");
6879 r_refdef.view.clear = true;
6881 // this produces a bloom texture to be used in R_BlendView() later
6882 if (r_bloomstate.hdr)
6884 R_HDR_RenderBloomTexture();
6885 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6886 r_textureframe++; // used only by R_GetCurrentTexture
6889 r_refdef.view.showdebug = true;
6892 if (r_timereport_active)
6893 R_TimeReport("visibility");
6895 R_Shadow_UpdateBounceGridTexture();
6896 if (r_timereport_active && r_shadow_bouncegrid.integer)
6897 R_TimeReport("bouncegrid");
6899 r_waterstate.numwaterplanes = 0;
6900 if (r_waterstate.enabled)
6901 R_RenderWaterPlanes();
6904 r_waterstate.numwaterplanes = 0;
6907 if (r_timereport_active)
6908 R_TimeReport("blendview");
6910 GL_Scissor(0, 0, vid.width, vid.height);
6911 GL_ScissorTest(false);
6913 r_refdef.view.matrix = originalmatrix;
6918 void R_RenderWaterPlanes(void)
6920 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6922 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6923 if (r_timereport_active)
6924 R_TimeReport("waterworld");
6927 // don't let sound skip if going slow
6928 if (r_refdef.scene.extraupdate)
6931 R_DrawModelsAddWaterPlanes();
6932 if (r_timereport_active)
6933 R_TimeReport("watermodels");
6935 if (r_waterstate.numwaterplanes)
6937 R_Water_ProcessPlanes();
6938 if (r_timereport_active)
6939 R_TimeReport("waterscenes");
6943 extern void R_DrawLightningBeams (void);
6944 extern void VM_CL_AddPolygonsToMeshQueue (void);
6945 extern void R_DrawPortals (void);
6946 extern cvar_t cl_locs_show;
6947 static void R_DrawLocs(void);
6948 static void R_DrawEntityBBoxes(void);
6949 static void R_DrawModelDecals(void);
6950 extern void R_DrawModelShadows(void);
6951 extern void R_DrawModelShadowMaps(void);
6952 extern cvar_t cl_decals_newsystem;
6953 extern qboolean r_shadow_usingdeferredprepass;
6954 void R_RenderScene(void)
6956 qboolean shadowmapping = false;
6958 if (r_timereport_active)
6959 R_TimeReport("beginscene");
6961 r_refdef.stats.renders++;
6965 // don't let sound skip if going slow
6966 if (r_refdef.scene.extraupdate)
6969 R_MeshQueue_BeginScene();
6973 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);
6975 if (r_timereport_active)
6976 R_TimeReport("skystartframe");
6978 if (cl.csqc_vidvars.drawworld)
6980 // don't let sound skip if going slow
6981 if (r_refdef.scene.extraupdate)
6984 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6986 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6987 if (r_timereport_active)
6988 R_TimeReport("worldsky");
6991 if (R_DrawBrushModelsSky() && r_timereport_active)
6992 R_TimeReport("bmodelsky");
6994 if (skyrendermasked && skyrenderlater)
6996 // we have to force off the water clipping plane while rendering sky
7000 if (r_timereport_active)
7001 R_TimeReport("sky");
7005 R_AnimCache_CacheVisibleEntities();
7006 if (r_timereport_active)
7007 R_TimeReport("animation");
7009 R_Shadow_PrepareLights();
7010 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7011 R_Shadow_PrepareModelShadows();
7012 if (r_timereport_active)
7013 R_TimeReport("preparelights");
7015 if (R_Shadow_ShadowMappingEnabled())
7016 shadowmapping = true;
7018 if (r_shadow_usingdeferredprepass)
7019 R_Shadow_DrawPrepass();
7021 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7023 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7024 if (r_timereport_active)
7025 R_TimeReport("worlddepth");
7027 if (r_depthfirst.integer >= 2)
7029 R_DrawModelsDepth();
7030 if (r_timereport_active)
7031 R_TimeReport("modeldepth");
7034 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7036 R_DrawModelShadowMaps();
7037 R_ResetViewRendering3D();
7038 // don't let sound skip if going slow
7039 if (r_refdef.scene.extraupdate)
7043 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7045 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7046 if (r_timereport_active)
7047 R_TimeReport("world");
7050 // don't let sound skip if going slow
7051 if (r_refdef.scene.extraupdate)
7055 if (r_timereport_active)
7056 R_TimeReport("models");
7058 // don't let sound skip if going slow
7059 if (r_refdef.scene.extraupdate)
7062 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7064 R_DrawModelShadows();
7065 R_ResetViewRendering3D();
7066 // don't let sound skip if going slow
7067 if (r_refdef.scene.extraupdate)
7071 if (!r_shadow_usingdeferredprepass)
7073 R_Shadow_DrawLights();
7074 if (r_timereport_active)
7075 R_TimeReport("rtlights");
7078 // don't let sound skip if going slow
7079 if (r_refdef.scene.extraupdate)
7082 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7084 R_DrawModelShadows();
7085 R_ResetViewRendering3D();
7086 // don't let sound skip if going slow
7087 if (r_refdef.scene.extraupdate)
7091 if (cl.csqc_vidvars.drawworld)
7093 if (cl_decals_newsystem.integer)
7095 R_DrawModelDecals();
7096 if (r_timereport_active)
7097 R_TimeReport("modeldecals");
7102 if (r_timereport_active)
7103 R_TimeReport("decals");
7107 if (r_timereport_active)
7108 R_TimeReport("particles");
7111 if (r_timereport_active)
7112 R_TimeReport("explosions");
7114 R_DrawLightningBeams();
7115 if (r_timereport_active)
7116 R_TimeReport("lightning");
7119 VM_CL_AddPolygonsToMeshQueue();
7121 if (r_refdef.view.showdebug)
7123 if (cl_locs_show.integer)
7126 if (r_timereport_active)
7127 R_TimeReport("showlocs");
7130 if (r_drawportals.integer)
7133 if (r_timereport_active)
7134 R_TimeReport("portals");
7137 if (r_showbboxes.value > 0)
7139 R_DrawEntityBBoxes();
7140 if (r_timereport_active)
7141 R_TimeReport("bboxes");
7145 if (r_transparent.integer)
7147 R_MeshQueue_RenderTransparent();
7148 if (r_timereport_active)
7149 R_TimeReport("drawtrans");
7152 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))
7154 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7155 if (r_timereport_active)
7156 R_TimeReport("worlddebug");
7157 R_DrawModelsDebug();
7158 if (r_timereport_active)
7159 R_TimeReport("modeldebug");
7162 if (cl.csqc_vidvars.drawworld)
7164 R_Shadow_DrawCoronas();
7165 if (r_timereport_active)
7166 R_TimeReport("coronas");
7171 GL_DepthTest(false);
7172 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7173 GL_Color(1, 1, 1, 1);
7174 qglBegin(GL_POLYGON);
7175 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7176 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7177 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7178 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7180 qglBegin(GL_POLYGON);
7181 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]);
7182 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]);
7183 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]);
7184 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]);
7186 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7190 // don't let sound skip if going slow
7191 if (r_refdef.scene.extraupdate)
7194 R_ResetViewRendering2D();
7197 static const unsigned short bboxelements[36] =
7207 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7210 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7212 RSurf_ActiveWorldEntity();
7214 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7215 GL_DepthMask(false);
7216 GL_DepthRange(0, 1);
7217 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7218 // R_Mesh_ResetTextureState();
7220 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7221 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7222 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7223 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7224 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7225 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7226 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7227 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7228 R_FillColors(color4f, 8, cr, cg, cb, ca);
7229 if (r_refdef.fogenabled)
7231 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7233 f1 = RSurf_FogVertex(v);
7235 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7236 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7237 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7240 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7241 R_Mesh_ResetTextureState();
7242 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7243 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7246 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7250 prvm_edict_t *edict;
7251 prvm_prog_t *prog_save = prog;
7253 // this function draws bounding boxes of server entities
7257 GL_CullFace(GL_NONE);
7258 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7262 for (i = 0;i < numsurfaces;i++)
7264 edict = PRVM_EDICT_NUM(surfacelist[i]);
7265 switch ((int)PRVM_serveredictfloat(edict, solid))
7267 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7268 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7269 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7270 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7271 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7272 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7274 color[3] *= r_showbboxes.value;
7275 color[3] = bound(0, color[3], 1);
7276 GL_DepthTest(!r_showdisabledepthtest.integer);
7277 GL_CullFace(r_refdef.view.cullface_front);
7278 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7284 static void R_DrawEntityBBoxes(void)
7287 prvm_edict_t *edict;
7289 prvm_prog_t *prog_save = prog;
7291 // this function draws bounding boxes of server entities
7297 for (i = 0;i < prog->num_edicts;i++)
7299 edict = PRVM_EDICT_NUM(i);
7300 if (edict->priv.server->free)
7302 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7303 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7305 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7307 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7308 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7314 static const int nomodelelement3i[24] =
7326 static const unsigned short nomodelelement3s[24] =
7338 static const float nomodelvertex3f[6*3] =
7348 static const float nomodelcolor4f[6*4] =
7350 0.0f, 0.0f, 0.5f, 1.0f,
7351 0.0f, 0.0f, 0.5f, 1.0f,
7352 0.0f, 0.5f, 0.0f, 1.0f,
7353 0.0f, 0.5f, 0.0f, 1.0f,
7354 0.5f, 0.0f, 0.0f, 1.0f,
7355 0.5f, 0.0f, 0.0f, 1.0f
7358 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7364 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);
7366 // this is only called once per entity so numsurfaces is always 1, and
7367 // surfacelist is always {0}, so this code does not handle batches
7369 if (rsurface.ent_flags & RENDER_ADDITIVE)
7371 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7372 GL_DepthMask(false);
7374 else if (rsurface.colormod[3] < 1)
7376 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7377 GL_DepthMask(false);
7381 GL_BlendFunc(GL_ONE, GL_ZERO);
7384 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7385 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7386 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7387 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7388 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7389 for (i = 0, c = color4f;i < 6;i++, c += 4)
7391 c[0] *= rsurface.colormod[0];
7392 c[1] *= rsurface.colormod[1];
7393 c[2] *= rsurface.colormod[2];
7394 c[3] *= rsurface.colormod[3];
7396 if (r_refdef.fogenabled)
7398 for (i = 0, c = color4f;i < 6;i++, c += 4)
7400 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7402 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7403 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7404 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7407 // R_Mesh_ResetTextureState();
7408 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7409 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7410 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7413 void R_DrawNoModel(entity_render_t *ent)
7416 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7417 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7418 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7420 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7423 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7425 vec3_t right1, right2, diff, normal;
7427 VectorSubtract (org2, org1, normal);
7429 // calculate 'right' vector for start
7430 VectorSubtract (r_refdef.view.origin, org1, diff);
7431 CrossProduct (normal, diff, right1);
7432 VectorNormalize (right1);
7434 // calculate 'right' vector for end
7435 VectorSubtract (r_refdef.view.origin, org2, diff);
7436 CrossProduct (normal, diff, right2);
7437 VectorNormalize (right2);
7439 vert[ 0] = org1[0] + width * right1[0];
7440 vert[ 1] = org1[1] + width * right1[1];
7441 vert[ 2] = org1[2] + width * right1[2];
7442 vert[ 3] = org1[0] - width * right1[0];
7443 vert[ 4] = org1[1] - width * right1[1];
7444 vert[ 5] = org1[2] - width * right1[2];
7445 vert[ 6] = org2[0] - width * right2[0];
7446 vert[ 7] = org2[1] - width * right2[1];
7447 vert[ 8] = org2[2] - width * right2[2];
7448 vert[ 9] = org2[0] + width * right2[0];
7449 vert[10] = org2[1] + width * right2[1];
7450 vert[11] = org2[2] + width * right2[2];
7453 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)
7455 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7456 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7457 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7458 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7459 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7460 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7461 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7462 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7463 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7464 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7465 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7466 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7469 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7474 VectorSet(v, x, y, z);
7475 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7476 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7478 if (i == mesh->numvertices)
7480 if (mesh->numvertices < mesh->maxvertices)
7482 VectorCopy(v, vertex3f);
7483 mesh->numvertices++;
7485 return mesh->numvertices;
7491 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7495 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7496 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7497 e = mesh->element3i + mesh->numtriangles * 3;
7498 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7500 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7501 if (mesh->numtriangles < mesh->maxtriangles)
7506 mesh->numtriangles++;
7508 element[1] = element[2];
7512 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7516 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7517 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7518 e = mesh->element3i + mesh->numtriangles * 3;
7519 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7521 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7522 if (mesh->numtriangles < mesh->maxtriangles)
7527 mesh->numtriangles++;
7529 element[1] = element[2];
7533 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7534 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7536 int planenum, planenum2;
7539 mplane_t *plane, *plane2;
7541 double temppoints[2][256*3];
7542 // figure out how large a bounding box we need to properly compute this brush
7544 for (w = 0;w < numplanes;w++)
7545 maxdist = max(maxdist, fabs(planes[w].dist));
7546 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7547 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7548 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7552 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7553 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7555 if (planenum2 == planenum)
7557 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);
7560 if (tempnumpoints < 3)
7562 // generate elements forming a triangle fan for this polygon
7563 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7567 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)
7569 texturelayer_t *layer;
7570 layer = t->currentlayers + t->currentnumlayers++;
7572 layer->depthmask = depthmask;
7573 layer->blendfunc1 = blendfunc1;
7574 layer->blendfunc2 = blendfunc2;
7575 layer->texture = texture;
7576 layer->texmatrix = *matrix;
7577 layer->color[0] = r;
7578 layer->color[1] = g;
7579 layer->color[2] = b;
7580 layer->color[3] = a;
7583 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7585 if(parms[0] == 0 && parms[1] == 0)
7587 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7588 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7593 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7596 index = parms[2] + rsurface.shadertime * parms[3];
7597 index -= floor(index);
7598 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7601 case Q3WAVEFUNC_NONE:
7602 case Q3WAVEFUNC_NOISE:
7603 case Q3WAVEFUNC_COUNT:
7606 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7607 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7608 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7609 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7610 case Q3WAVEFUNC_TRIANGLE:
7612 f = index - floor(index);
7625 f = parms[0] + parms[1] * f;
7626 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7627 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7631 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7637 matrix4x4_t matrix, temp;
7638 switch(tcmod->tcmod)
7642 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7643 matrix = r_waterscrollmatrix;
7645 matrix = identitymatrix;
7647 case Q3TCMOD_ENTITYTRANSLATE:
7648 // this is used in Q3 to allow the gamecode to control texcoord
7649 // scrolling on the entity, which is not supported in darkplaces yet.
7650 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7652 case Q3TCMOD_ROTATE:
7653 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7654 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7655 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7658 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7660 case Q3TCMOD_SCROLL:
7661 // extra care is needed because of precision breakdown with large values of time
7662 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7663 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7664 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7666 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7667 w = (int) tcmod->parms[0];
7668 h = (int) tcmod->parms[1];
7669 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7671 idx = (int) floor(f * w * h);
7672 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7674 case Q3TCMOD_STRETCH:
7675 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7676 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7678 case Q3TCMOD_TRANSFORM:
7679 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7680 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7681 VectorSet(tcmat + 6, 0 , 0 , 1);
7682 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7683 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7685 case Q3TCMOD_TURBULENT:
7686 // this is handled in the RSurf_PrepareVertices function
7687 matrix = identitymatrix;
7691 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7694 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7696 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7697 char name[MAX_QPATH];
7698 skinframe_t *skinframe;
7699 unsigned char pixels[296*194];
7700 strlcpy(cache->name, skinname, sizeof(cache->name));
7701 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7702 if (developer_loading.integer)
7703 Con_Printf("loading %s\n", name);
7704 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7705 if (!skinframe || !skinframe->base)
7708 fs_offset_t filesize;
7710 f = FS_LoadFile(name, tempmempool, true, &filesize);
7713 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7714 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7718 cache->skinframe = skinframe;
7721 texture_t *R_GetCurrentTexture(texture_t *t)
7724 const entity_render_t *ent = rsurface.entity;
7725 dp_model_t *model = ent->model;
7726 q3shaderinfo_layer_tcmod_t *tcmod;
7728 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7729 return t->currentframe;
7730 t->update_lastrenderframe = r_textureframe;
7731 t->update_lastrenderentity = (void *)ent;
7733 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7734 t->camera_entity = ent->entitynumber;
7736 t->camera_entity = 0;
7738 // switch to an alternate material if this is a q1bsp animated material
7740 texture_t *texture = t;
7741 int s = rsurface.ent_skinnum;
7742 if ((unsigned int)s >= (unsigned int)model->numskins)
7744 if (model->skinscenes)
7746 if (model->skinscenes[s].framecount > 1)
7747 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7749 s = model->skinscenes[s].firstframe;
7752 t = t + s * model->num_surfaces;
7755 // use an alternate animation if the entity's frame is not 0,
7756 // and only if the texture has an alternate animation
7757 if (rsurface.ent_alttextures && t->anim_total[1])
7758 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7760 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7762 texture->currentframe = t;
7765 // update currentskinframe to be a qw skin or animation frame
7766 if (rsurface.ent_qwskin >= 0)
7768 i = rsurface.ent_qwskin;
7769 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7771 r_qwskincache_size = cl.maxclients;
7773 Mem_Free(r_qwskincache);
7774 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7776 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7777 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7778 t->currentskinframe = r_qwskincache[i].skinframe;
7779 if (t->currentskinframe == NULL)
7780 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7782 else if (t->numskinframes >= 2)
7783 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7784 if (t->backgroundnumskinframes >= 2)
7785 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7787 t->currentmaterialflags = t->basematerialflags;
7788 t->currentalpha = rsurface.colormod[3];
7789 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7790 t->currentalpha *= r_wateralpha.value;
7791 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7792 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7793 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7794 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7795 if (!(rsurface.ent_flags & RENDER_LIGHT))
7796 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7797 else if (FAKELIGHT_ENABLED)
7799 // no modellight if using fakelight for the map
7801 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7803 // pick a model lighting mode
7804 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7805 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7807 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7809 if (rsurface.ent_flags & RENDER_ADDITIVE)
7810 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7811 else if (t->currentalpha < 1)
7812 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7813 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7814 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7815 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7816 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7817 if (t->backgroundnumskinframes)
7818 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7819 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7821 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7822 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7825 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7826 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7828 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7829 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7831 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7832 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7834 // there is no tcmod
7835 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7837 t->currenttexmatrix = r_waterscrollmatrix;
7838 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7840 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7842 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7843 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7846 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7847 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7848 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7849 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7851 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7852 if (t->currentskinframe->qpixels)
7853 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7854 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7855 if (!t->basetexture)
7856 t->basetexture = r_texture_notexture;
7857 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7858 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7859 t->nmaptexture = t->currentskinframe->nmap;
7860 if (!t->nmaptexture)
7861 t->nmaptexture = r_texture_blanknormalmap;
7862 t->glosstexture = r_texture_black;
7863 t->glowtexture = t->currentskinframe->glow;
7864 t->fogtexture = t->currentskinframe->fog;
7865 t->reflectmasktexture = t->currentskinframe->reflect;
7866 if (t->backgroundnumskinframes)
7868 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7869 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7870 t->backgroundglosstexture = r_texture_black;
7871 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7872 if (!t->backgroundnmaptexture)
7873 t->backgroundnmaptexture = r_texture_blanknormalmap;
7877 t->backgroundbasetexture = r_texture_white;
7878 t->backgroundnmaptexture = r_texture_blanknormalmap;
7879 t->backgroundglosstexture = r_texture_black;
7880 t->backgroundglowtexture = NULL;
7882 t->specularpower = r_shadow_glossexponent.value;
7883 // TODO: store reference values for these in the texture?
7884 t->specularscale = 0;
7885 if (r_shadow_gloss.integer > 0)
7887 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7889 if (r_shadow_glossintensity.value > 0)
7891 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7892 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7893 t->specularscale = r_shadow_glossintensity.value;
7896 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7898 t->glosstexture = r_texture_white;
7899 t->backgroundglosstexture = r_texture_white;
7900 t->specularscale = r_shadow_gloss2intensity.value;
7901 t->specularpower = r_shadow_gloss2exponent.value;
7904 t->specularscale *= t->specularscalemod;
7905 t->specularpower *= t->specularpowermod;
7906 t->rtlightambient = 0;
7908 // lightmaps mode looks bad with dlights using actual texturing, so turn
7909 // off the colormap and glossmap, but leave the normalmap on as it still
7910 // accurately represents the shading involved
7911 if (gl_lightmaps.integer)
7913 t->basetexture = r_texture_grey128;
7914 t->pantstexture = r_texture_black;
7915 t->shirttexture = r_texture_black;
7916 t->nmaptexture = r_texture_blanknormalmap;
7917 t->glosstexture = r_texture_black;
7918 t->glowtexture = NULL;
7919 t->fogtexture = NULL;
7920 t->reflectmasktexture = NULL;
7921 t->backgroundbasetexture = NULL;
7922 t->backgroundnmaptexture = r_texture_blanknormalmap;
7923 t->backgroundglosstexture = r_texture_black;
7924 t->backgroundglowtexture = NULL;
7925 t->specularscale = 0;
7926 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7929 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7930 VectorClear(t->dlightcolor);
7931 t->currentnumlayers = 0;
7932 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7934 int blendfunc1, blendfunc2;
7936 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7938 blendfunc1 = GL_SRC_ALPHA;
7939 blendfunc2 = GL_ONE;
7941 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7943 blendfunc1 = GL_SRC_ALPHA;
7944 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7946 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7948 blendfunc1 = t->customblendfunc[0];
7949 blendfunc2 = t->customblendfunc[1];
7953 blendfunc1 = GL_ONE;
7954 blendfunc2 = GL_ZERO;
7956 // don't colormod evilblend textures
7957 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7958 VectorSet(t->lightmapcolor, 1, 1, 1);
7959 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7960 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7962 // fullbright is not affected by r_refdef.lightmapintensity
7963 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]);
7964 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7965 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]);
7966 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7967 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]);
7971 vec3_t ambientcolor;
7973 // set the color tint used for lights affecting this surface
7974 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7976 // q3bsp has no lightmap updates, so the lightstylevalue that
7977 // would normally be baked into the lightmap must be
7978 // applied to the color
7979 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7980 if (model->type == mod_brushq3)
7981 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7982 colorscale *= r_refdef.lightmapintensity;
7983 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7984 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7985 // basic lit geometry
7986 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]);
7987 // add pants/shirt if needed
7988 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7989 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]);
7990 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7991 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]);
7992 // now add ambient passes if needed
7993 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7995 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]);
7996 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7997 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]);
7998 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7999 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]);
8002 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8003 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]);
8004 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8006 // if this is opaque use alpha blend which will darken the earlier
8009 // if this is an alpha blended material, all the earlier passes
8010 // were darkened by fog already, so we only need to add the fog
8011 // color ontop through the fog mask texture
8013 // if this is an additive blended material, all the earlier passes
8014 // were darkened by fog already, and we should not add fog color
8015 // (because the background was not darkened, there is no fog color
8016 // that was lost behind it).
8017 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]);
8021 return t->currentframe;
8024 rsurfacestate_t rsurface;
8026 void RSurf_ActiveWorldEntity(void)
8028 dp_model_t *model = r_refdef.scene.worldmodel;
8029 //if (rsurface.entity == r_refdef.scene.worldentity)
8031 rsurface.entity = r_refdef.scene.worldentity;
8032 rsurface.skeleton = NULL;
8033 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8034 rsurface.ent_skinnum = 0;
8035 rsurface.ent_qwskin = -1;
8036 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8037 rsurface.shadertime = r_refdef.scene.time;
8038 rsurface.matrix = identitymatrix;
8039 rsurface.inversematrix = identitymatrix;
8040 rsurface.matrixscale = 1;
8041 rsurface.inversematrixscale = 1;
8042 R_EntityMatrix(&identitymatrix);
8043 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8044 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8045 rsurface.fograngerecip = r_refdef.fograngerecip;
8046 rsurface.fogheightfade = r_refdef.fogheightfade;
8047 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8048 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8049 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8050 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8051 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8052 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8053 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8054 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8055 rsurface.colormod[3] = 1;
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;
8062 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8063 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8064 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8065 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8066 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8067 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8068 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8069 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8070 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8071 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8072 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8073 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8074 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8075 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8076 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8077 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8078 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8079 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8080 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8081 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8082 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8083 rsurface.modelelement3i = model->surfmesh.data_element3i;
8084 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8085 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8086 rsurface.modelelement3s = model->surfmesh.data_element3s;
8087 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8088 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8089 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8090 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8091 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8092 rsurface.modelsurfaces = model->data_surfaces;
8093 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8094 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8095 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8096 rsurface.modelgeneratedvertex = false;
8097 rsurface.batchgeneratedvertex = false;
8098 rsurface.batchfirstvertex = 0;
8099 rsurface.batchnumvertices = 0;
8100 rsurface.batchfirsttriangle = 0;
8101 rsurface.batchnumtriangles = 0;
8102 rsurface.batchvertex3f = NULL;
8103 rsurface.batchvertex3f_vertexbuffer = NULL;
8104 rsurface.batchvertex3f_bufferoffset = 0;
8105 rsurface.batchsvector3f = NULL;
8106 rsurface.batchsvector3f_vertexbuffer = NULL;
8107 rsurface.batchsvector3f_bufferoffset = 0;
8108 rsurface.batchtvector3f = NULL;
8109 rsurface.batchtvector3f_vertexbuffer = NULL;
8110 rsurface.batchtvector3f_bufferoffset = 0;
8111 rsurface.batchnormal3f = NULL;
8112 rsurface.batchnormal3f_vertexbuffer = NULL;
8113 rsurface.batchnormal3f_bufferoffset = 0;
8114 rsurface.batchlightmapcolor4f = NULL;
8115 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8116 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8117 rsurface.batchtexcoordtexture2f = NULL;
8118 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8119 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8120 rsurface.batchtexcoordlightmap2f = NULL;
8121 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8122 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8123 rsurface.batchvertexmesh = NULL;
8124 rsurface.batchvertexmeshbuffer = NULL;
8125 rsurface.batchvertex3fbuffer = NULL;
8126 rsurface.batchelement3i = NULL;
8127 rsurface.batchelement3i_indexbuffer = NULL;
8128 rsurface.batchelement3i_bufferoffset = 0;
8129 rsurface.batchelement3s = NULL;
8130 rsurface.batchelement3s_indexbuffer = NULL;
8131 rsurface.batchelement3s_bufferoffset = 0;
8132 rsurface.passcolor4f = NULL;
8133 rsurface.passcolor4f_vertexbuffer = NULL;
8134 rsurface.passcolor4f_bufferoffset = 0;
8137 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8139 dp_model_t *model = ent->model;
8140 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8142 rsurface.entity = (entity_render_t *)ent;
8143 rsurface.skeleton = ent->skeleton;
8144 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8145 rsurface.ent_skinnum = ent->skinnum;
8146 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;
8147 rsurface.ent_flags = ent->flags;
8148 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8149 rsurface.matrix = ent->matrix;
8150 rsurface.inversematrix = ent->inversematrix;
8151 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8152 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8153 R_EntityMatrix(&rsurface.matrix);
8154 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8155 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8156 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8157 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8158 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8159 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8160 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8161 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8162 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8163 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8164 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8165 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8166 rsurface.colormod[3] = ent->alpha;
8167 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8168 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8169 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8170 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8171 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8172 if (ent->model->brush.submodel && !prepass)
8174 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8175 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8177 if (model->surfmesh.isanimated && model->AnimateVertices)
8179 if (ent->animcache_vertex3f)
8181 rsurface.modelvertex3f = ent->animcache_vertex3f;
8182 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8183 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8184 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8185 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8186 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8187 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8189 else if (wanttangents)
8191 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8192 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8193 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8194 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8195 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8196 rsurface.modelvertexmesh = NULL;
8197 rsurface.modelvertexmeshbuffer = NULL;
8198 rsurface.modelvertex3fbuffer = NULL;
8200 else if (wantnormals)
8202 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8203 rsurface.modelsvector3f = NULL;
8204 rsurface.modeltvector3f = NULL;
8205 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8206 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8207 rsurface.modelvertexmesh = NULL;
8208 rsurface.modelvertexmeshbuffer = NULL;
8209 rsurface.modelvertex3fbuffer = NULL;
8213 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8214 rsurface.modelsvector3f = NULL;
8215 rsurface.modeltvector3f = NULL;
8216 rsurface.modelnormal3f = NULL;
8217 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8218 rsurface.modelvertexmesh = NULL;
8219 rsurface.modelvertexmeshbuffer = NULL;
8220 rsurface.modelvertex3fbuffer = NULL;
8222 rsurface.modelvertex3f_vertexbuffer = 0;
8223 rsurface.modelvertex3f_bufferoffset = 0;
8224 rsurface.modelsvector3f_vertexbuffer = 0;
8225 rsurface.modelsvector3f_bufferoffset = 0;
8226 rsurface.modeltvector3f_vertexbuffer = 0;
8227 rsurface.modeltvector3f_bufferoffset = 0;
8228 rsurface.modelnormal3f_vertexbuffer = 0;
8229 rsurface.modelnormal3f_bufferoffset = 0;
8230 rsurface.modelgeneratedvertex = true;
8234 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8235 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8236 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8237 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8238 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8239 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8240 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8241 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8242 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8243 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8244 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8245 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8246 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8247 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8248 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8249 rsurface.modelgeneratedvertex = false;
8251 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8252 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8253 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8254 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8255 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8256 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8257 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8258 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8259 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8260 rsurface.modelelement3i = model->surfmesh.data_element3i;
8261 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8262 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8263 rsurface.modelelement3s = model->surfmesh.data_element3s;
8264 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8265 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8266 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8267 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8268 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8269 rsurface.modelsurfaces = model->data_surfaces;
8270 rsurface.batchgeneratedvertex = false;
8271 rsurface.batchfirstvertex = 0;
8272 rsurface.batchnumvertices = 0;
8273 rsurface.batchfirsttriangle = 0;
8274 rsurface.batchnumtriangles = 0;
8275 rsurface.batchvertex3f = NULL;
8276 rsurface.batchvertex3f_vertexbuffer = NULL;
8277 rsurface.batchvertex3f_bufferoffset = 0;
8278 rsurface.batchsvector3f = NULL;
8279 rsurface.batchsvector3f_vertexbuffer = NULL;
8280 rsurface.batchsvector3f_bufferoffset = 0;
8281 rsurface.batchtvector3f = NULL;
8282 rsurface.batchtvector3f_vertexbuffer = NULL;
8283 rsurface.batchtvector3f_bufferoffset = 0;
8284 rsurface.batchnormal3f = NULL;
8285 rsurface.batchnormal3f_vertexbuffer = NULL;
8286 rsurface.batchnormal3f_bufferoffset = 0;
8287 rsurface.batchlightmapcolor4f = NULL;
8288 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8289 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8290 rsurface.batchtexcoordtexture2f = NULL;
8291 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8292 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8293 rsurface.batchtexcoordlightmap2f = NULL;
8294 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8295 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8296 rsurface.batchvertexmesh = NULL;
8297 rsurface.batchvertexmeshbuffer = NULL;
8298 rsurface.batchvertex3fbuffer = NULL;
8299 rsurface.batchelement3i = NULL;
8300 rsurface.batchelement3i_indexbuffer = NULL;
8301 rsurface.batchelement3i_bufferoffset = 0;
8302 rsurface.batchelement3s = NULL;
8303 rsurface.batchelement3s_indexbuffer = NULL;
8304 rsurface.batchelement3s_bufferoffset = 0;
8305 rsurface.passcolor4f = NULL;
8306 rsurface.passcolor4f_vertexbuffer = NULL;
8307 rsurface.passcolor4f_bufferoffset = 0;
8310 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)
8312 rsurface.entity = r_refdef.scene.worldentity;
8313 rsurface.skeleton = NULL;
8314 rsurface.ent_skinnum = 0;
8315 rsurface.ent_qwskin = -1;
8316 rsurface.ent_flags = entflags;
8317 rsurface.shadertime = r_refdef.scene.time - shadertime;
8318 rsurface.modelnumvertices = numvertices;
8319 rsurface.modelnumtriangles = numtriangles;
8320 rsurface.matrix = *matrix;
8321 rsurface.inversematrix = *inversematrix;
8322 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8323 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8324 R_EntityMatrix(&rsurface.matrix);
8325 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8326 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8327 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8328 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8329 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8330 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8331 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8332 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8333 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8334 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8335 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8336 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8337 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);
8338 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8339 rsurface.frameblend[0].lerp = 1;
8340 rsurface.ent_alttextures = false;
8341 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8342 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8345 rsurface.modelvertex3f = (float *)vertex3f;
8346 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8347 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8348 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8350 else if (wantnormals)
8352 rsurface.modelvertex3f = (float *)vertex3f;
8353 rsurface.modelsvector3f = NULL;
8354 rsurface.modeltvector3f = NULL;
8355 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8359 rsurface.modelvertex3f = (float *)vertex3f;
8360 rsurface.modelsvector3f = NULL;
8361 rsurface.modeltvector3f = NULL;
8362 rsurface.modelnormal3f = NULL;
8364 rsurface.modelvertexmesh = NULL;
8365 rsurface.modelvertexmeshbuffer = NULL;
8366 rsurface.modelvertex3fbuffer = NULL;
8367 rsurface.modelvertex3f_vertexbuffer = 0;
8368 rsurface.modelvertex3f_bufferoffset = 0;
8369 rsurface.modelsvector3f_vertexbuffer = 0;
8370 rsurface.modelsvector3f_bufferoffset = 0;
8371 rsurface.modeltvector3f_vertexbuffer = 0;
8372 rsurface.modeltvector3f_bufferoffset = 0;
8373 rsurface.modelnormal3f_vertexbuffer = 0;
8374 rsurface.modelnormal3f_bufferoffset = 0;
8375 rsurface.modelgeneratedvertex = true;
8376 rsurface.modellightmapcolor4f = (float *)color4f;
8377 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8378 rsurface.modellightmapcolor4f_bufferoffset = 0;
8379 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8380 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8381 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8382 rsurface.modeltexcoordlightmap2f = NULL;
8383 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8384 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8385 rsurface.modelelement3i = (int *)element3i;
8386 rsurface.modelelement3i_indexbuffer = NULL;
8387 rsurface.modelelement3i_bufferoffset = 0;
8388 rsurface.modelelement3s = (unsigned short *)element3s;
8389 rsurface.modelelement3s_indexbuffer = NULL;
8390 rsurface.modelelement3s_bufferoffset = 0;
8391 rsurface.modellightmapoffsets = NULL;
8392 rsurface.modelsurfaces = NULL;
8393 rsurface.batchgeneratedvertex = false;
8394 rsurface.batchfirstvertex = 0;
8395 rsurface.batchnumvertices = 0;
8396 rsurface.batchfirsttriangle = 0;
8397 rsurface.batchnumtriangles = 0;
8398 rsurface.batchvertex3f = NULL;
8399 rsurface.batchvertex3f_vertexbuffer = NULL;
8400 rsurface.batchvertex3f_bufferoffset = 0;
8401 rsurface.batchsvector3f = NULL;
8402 rsurface.batchsvector3f_vertexbuffer = NULL;
8403 rsurface.batchsvector3f_bufferoffset = 0;
8404 rsurface.batchtvector3f = NULL;
8405 rsurface.batchtvector3f_vertexbuffer = NULL;
8406 rsurface.batchtvector3f_bufferoffset = 0;
8407 rsurface.batchnormal3f = NULL;
8408 rsurface.batchnormal3f_vertexbuffer = NULL;
8409 rsurface.batchnormal3f_bufferoffset = 0;
8410 rsurface.batchlightmapcolor4f = NULL;
8411 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8412 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8413 rsurface.batchtexcoordtexture2f = NULL;
8414 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8415 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8416 rsurface.batchtexcoordlightmap2f = NULL;
8417 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8418 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8419 rsurface.batchvertexmesh = NULL;
8420 rsurface.batchvertexmeshbuffer = NULL;
8421 rsurface.batchvertex3fbuffer = NULL;
8422 rsurface.batchelement3i = NULL;
8423 rsurface.batchelement3i_indexbuffer = NULL;
8424 rsurface.batchelement3i_bufferoffset = 0;
8425 rsurface.batchelement3s = NULL;
8426 rsurface.batchelement3s_indexbuffer = NULL;
8427 rsurface.batchelement3s_bufferoffset = 0;
8428 rsurface.passcolor4f = NULL;
8429 rsurface.passcolor4f_vertexbuffer = NULL;
8430 rsurface.passcolor4f_bufferoffset = 0;
8432 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8434 if ((wantnormals || wanttangents) && !normal3f)
8436 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8437 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8439 if (wanttangents && !svector3f)
8441 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8442 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8443 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8448 float RSurf_FogPoint(const float *v)
8450 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8451 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8452 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8453 float FogHeightFade = r_refdef.fogheightfade;
8455 unsigned int fogmasktableindex;
8456 if (r_refdef.fogplaneviewabove)
8457 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8459 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8460 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8461 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8464 float RSurf_FogVertex(const float *v)
8466 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8467 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8468 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8469 float FogHeightFade = rsurface.fogheightfade;
8471 unsigned int fogmasktableindex;
8472 if (r_refdef.fogplaneviewabove)
8473 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8475 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8476 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8477 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8480 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8483 for (i = 0;i < numelements;i++)
8484 outelement3i[i] = inelement3i[i] + adjust;
8487 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8488 extern cvar_t gl_vbo;
8489 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8497 int surfacefirsttriangle;
8498 int surfacenumtriangles;
8499 int surfacefirstvertex;
8500 int surfaceendvertex;
8501 int surfacenumvertices;
8502 int batchnumvertices;
8503 int batchnumtriangles;
8507 qboolean dynamicvertex;
8511 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8513 q3shaderinfo_deform_t *deform;
8514 const msurface_t *surface, *firstsurface;
8515 r_vertexmesh_t *vertexmesh;
8516 if (!texturenumsurfaces)
8518 // find vertex range of this surface batch
8520 firstsurface = texturesurfacelist[0];
8521 firsttriangle = firstsurface->num_firsttriangle;
8522 batchnumvertices = 0;
8523 batchnumtriangles = 0;
8524 firstvertex = endvertex = firstsurface->num_firstvertex;
8525 for (i = 0;i < texturenumsurfaces;i++)
8527 surface = texturesurfacelist[i];
8528 if (surface != firstsurface + i)
8530 surfacefirstvertex = surface->num_firstvertex;
8531 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8532 surfacenumvertices = surface->num_vertices;
8533 surfacenumtriangles = surface->num_triangles;
8534 if (firstvertex > surfacefirstvertex)
8535 firstvertex = surfacefirstvertex;
8536 if (endvertex < surfaceendvertex)
8537 endvertex = surfaceendvertex;
8538 batchnumvertices += surfacenumvertices;
8539 batchnumtriangles += surfacenumtriangles;
8542 // we now know the vertex range used, and if there are any gaps in it
8543 rsurface.batchfirstvertex = firstvertex;
8544 rsurface.batchnumvertices = endvertex - firstvertex;
8545 rsurface.batchfirsttriangle = firsttriangle;
8546 rsurface.batchnumtriangles = batchnumtriangles;
8548 // this variable holds flags for which properties have been updated that
8549 // may require regenerating vertexmesh array...
8552 // check if any dynamic vertex processing must occur
8553 dynamicvertex = false;
8555 // if there is a chance of animated vertex colors, it's a dynamic batch
8556 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8558 dynamicvertex = true;
8559 batchneed |= BATCHNEED_NOGAPS;
8560 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8563 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8565 switch (deform->deform)
8568 case Q3DEFORM_PROJECTIONSHADOW:
8569 case Q3DEFORM_TEXT0:
8570 case Q3DEFORM_TEXT1:
8571 case Q3DEFORM_TEXT2:
8572 case Q3DEFORM_TEXT3:
8573 case Q3DEFORM_TEXT4:
8574 case Q3DEFORM_TEXT5:
8575 case Q3DEFORM_TEXT6:
8576 case Q3DEFORM_TEXT7:
8579 case Q3DEFORM_AUTOSPRITE:
8580 dynamicvertex = true;
8581 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8582 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8584 case Q3DEFORM_AUTOSPRITE2:
8585 dynamicvertex = true;
8586 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8587 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8589 case Q3DEFORM_NORMAL:
8590 dynamicvertex = true;
8591 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8592 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8595 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8596 break; // if wavefunc is a nop, ignore this transform
8597 dynamicvertex = true;
8598 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8599 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8601 case Q3DEFORM_BULGE:
8602 dynamicvertex = true;
8603 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8604 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8607 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8608 break; // if wavefunc is a nop, ignore this transform
8609 dynamicvertex = true;
8610 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8611 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8615 switch(rsurface.texture->tcgen.tcgen)
8618 case Q3TCGEN_TEXTURE:
8620 case Q3TCGEN_LIGHTMAP:
8621 dynamicvertex = true;
8622 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8623 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8625 case Q3TCGEN_VECTOR:
8626 dynamicvertex = true;
8627 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8628 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8630 case Q3TCGEN_ENVIRONMENT:
8631 dynamicvertex = true;
8632 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8633 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8636 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8638 dynamicvertex = true;
8639 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8640 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8643 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8645 dynamicvertex = true;
8646 batchneed |= BATCHNEED_NOGAPS;
8647 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8650 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8652 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8653 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8654 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8655 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8656 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8657 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8658 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8661 // when the model data has no vertex buffer (dynamic mesh), we need to
8663 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8664 batchneed |= BATCHNEED_NOGAPS;
8666 // if needsupdate, we have to do a dynamic vertex batch for sure
8667 if (needsupdate & batchneed)
8668 dynamicvertex = true;
8670 // see if we need to build vertexmesh from arrays
8671 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8672 dynamicvertex = true;
8674 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8675 // also some drivers strongly dislike firstvertex
8676 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8677 dynamicvertex = true;
8679 rsurface.batchvertex3f = rsurface.modelvertex3f;
8680 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8681 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8682 rsurface.batchsvector3f = rsurface.modelsvector3f;
8683 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8684 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8685 rsurface.batchtvector3f = rsurface.modeltvector3f;
8686 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8687 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8688 rsurface.batchnormal3f = rsurface.modelnormal3f;
8689 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8690 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8691 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8692 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8693 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8694 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8695 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8696 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8697 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8698 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8699 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8700 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8701 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8702 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8703 rsurface.batchelement3i = rsurface.modelelement3i;
8704 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8705 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8706 rsurface.batchelement3s = rsurface.modelelement3s;
8707 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8708 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8710 // if any dynamic vertex processing has to occur in software, we copy the
8711 // entire surface list together before processing to rebase the vertices
8712 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8714 // if any gaps exist and we do not have a static vertex buffer, we have to
8715 // copy the surface list together to avoid wasting upload bandwidth on the
8716 // vertices in the gaps.
8718 // if gaps exist and we have a static vertex buffer, we still have to
8719 // combine the index buffer ranges into one dynamic index buffer.
8721 // in all cases we end up with data that can be drawn in one call.
8725 // static vertex data, just set pointers...
8726 rsurface.batchgeneratedvertex = false;
8727 // if there are gaps, we want to build a combined index buffer,
8728 // otherwise use the original static buffer with an appropriate offset
8731 // build a new triangle elements array for this batch
8732 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8733 rsurface.batchfirsttriangle = 0;
8735 for (i = 0;i < texturenumsurfaces;i++)
8737 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8738 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8739 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8740 numtriangles += surfacenumtriangles;
8742 rsurface.batchelement3i_indexbuffer = NULL;
8743 rsurface.batchelement3i_bufferoffset = 0;
8744 rsurface.batchelement3s = NULL;
8745 rsurface.batchelement3s_indexbuffer = NULL;
8746 rsurface.batchelement3s_bufferoffset = 0;
8747 if (endvertex <= 65536)
8749 // make a 16bit (unsigned short) index array if possible
8750 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8751 for (i = 0;i < numtriangles*3;i++)
8752 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8758 // something needs software processing, do it for real...
8759 // we only directly handle separate array data in this case and then
8760 // generate interleaved data if needed...
8761 rsurface.batchgeneratedvertex = true;
8763 // now copy the vertex data into a combined array and make an index array
8764 // (this is what Quake3 does all the time)
8765 //if (gaps || rsurface.batchfirstvertex)
8767 rsurface.batchvertex3fbuffer = NULL;
8768 rsurface.batchvertexmesh = NULL;
8769 rsurface.batchvertexmeshbuffer = NULL;
8770 rsurface.batchvertex3f = NULL;
8771 rsurface.batchvertex3f_vertexbuffer = NULL;
8772 rsurface.batchvertex3f_bufferoffset = 0;
8773 rsurface.batchsvector3f = NULL;
8774 rsurface.batchsvector3f_vertexbuffer = NULL;
8775 rsurface.batchsvector3f_bufferoffset = 0;
8776 rsurface.batchtvector3f = NULL;
8777 rsurface.batchtvector3f_vertexbuffer = NULL;
8778 rsurface.batchtvector3f_bufferoffset = 0;
8779 rsurface.batchnormal3f = NULL;
8780 rsurface.batchnormal3f_vertexbuffer = NULL;
8781 rsurface.batchnormal3f_bufferoffset = 0;
8782 rsurface.batchlightmapcolor4f = NULL;
8783 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8784 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8785 rsurface.batchtexcoordtexture2f = NULL;
8786 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8787 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8788 rsurface.batchtexcoordlightmap2f = NULL;
8789 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8790 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8791 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8792 rsurface.batchelement3i_indexbuffer = NULL;
8793 rsurface.batchelement3i_bufferoffset = 0;
8794 rsurface.batchelement3s = NULL;
8795 rsurface.batchelement3s_indexbuffer = NULL;
8796 rsurface.batchelement3s_bufferoffset = 0;
8797 // we'll only be setting up certain arrays as needed
8798 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8799 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8800 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8801 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8802 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8803 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8804 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8806 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8807 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8809 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8810 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8811 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8812 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8813 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8814 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8817 for (i = 0;i < texturenumsurfaces;i++)
8819 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8820 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8821 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8822 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8823 // copy only the data requested
8824 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8825 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8826 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8828 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8830 if (rsurface.batchvertex3f)
8831 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8833 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8835 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8837 if (rsurface.modelnormal3f)
8838 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8840 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8842 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8844 if (rsurface.modelsvector3f)
8846 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8847 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8851 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8852 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8855 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8857 if (rsurface.modellightmapcolor4f)
8858 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8860 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8862 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8864 if (rsurface.modeltexcoordtexture2f)
8865 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8867 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8869 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8871 if (rsurface.modeltexcoordlightmap2f)
8872 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8874 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8877 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8878 numvertices += surfacenumvertices;
8879 numtriangles += surfacenumtriangles;
8882 // generate a 16bit index array as well if possible
8883 // (in general, dynamic batches fit)
8884 if (numvertices <= 65536)
8886 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8887 for (i = 0;i < numtriangles*3;i++)
8888 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8891 // since we've copied everything, the batch now starts at 0
8892 rsurface.batchfirstvertex = 0;
8893 rsurface.batchnumvertices = batchnumvertices;
8894 rsurface.batchfirsttriangle = 0;
8895 rsurface.batchnumtriangles = batchnumtriangles;
8898 // q1bsp surfaces rendered in vertex color mode have to have colors
8899 // calculated based on lightstyles
8900 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8902 // generate color arrays for the surfaces in this list
8907 const unsigned char *lm;
8908 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8909 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8910 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8912 for (i = 0;i < texturenumsurfaces;i++)
8914 surface = texturesurfacelist[i];
8915 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8916 surfacenumvertices = surface->num_vertices;
8917 if (surface->lightmapinfo->samples)
8919 for (j = 0;j < surfacenumvertices;j++)
8921 lm = surface->lightmapinfo->samples + offsets[j];
8922 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8923 VectorScale(lm, scale, c);
8924 if (surface->lightmapinfo->styles[1] != 255)
8926 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8928 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8929 VectorMA(c, scale, lm, c);
8930 if (surface->lightmapinfo->styles[2] != 255)
8933 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8934 VectorMA(c, scale, lm, c);
8935 if (surface->lightmapinfo->styles[3] != 255)
8938 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8939 VectorMA(c, scale, lm, c);
8946 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);
8952 for (j = 0;j < surfacenumvertices;j++)
8954 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8961 // if vertices are deformed (sprite flares and things in maps, possibly
8962 // water waves, bulges and other deformations), modify the copied vertices
8964 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8966 switch (deform->deform)
8969 case Q3DEFORM_PROJECTIONSHADOW:
8970 case Q3DEFORM_TEXT0:
8971 case Q3DEFORM_TEXT1:
8972 case Q3DEFORM_TEXT2:
8973 case Q3DEFORM_TEXT3:
8974 case Q3DEFORM_TEXT4:
8975 case Q3DEFORM_TEXT5:
8976 case Q3DEFORM_TEXT6:
8977 case Q3DEFORM_TEXT7:
8980 case Q3DEFORM_AUTOSPRITE:
8981 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8982 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8983 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8984 VectorNormalize(newforward);
8985 VectorNormalize(newright);
8986 VectorNormalize(newup);
8987 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8988 // rsurface.batchvertex3f_vertexbuffer = NULL;
8989 // rsurface.batchvertex3f_bufferoffset = 0;
8990 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8991 // rsurface.batchsvector3f_vertexbuffer = NULL;
8992 // rsurface.batchsvector3f_bufferoffset = 0;
8993 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8994 // rsurface.batchtvector3f_vertexbuffer = NULL;
8995 // rsurface.batchtvector3f_bufferoffset = 0;
8996 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8997 // rsurface.batchnormal3f_vertexbuffer = NULL;
8998 // rsurface.batchnormal3f_bufferoffset = 0;
8999 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9000 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9001 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9002 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9003 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);
9004 // a single autosprite surface can contain multiple sprites...
9005 for (j = 0;j < batchnumvertices - 3;j += 4)
9007 VectorClear(center);
9008 for (i = 0;i < 4;i++)
9009 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9010 VectorScale(center, 0.25f, center);
9011 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9012 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9013 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9014 for (i = 0;i < 4;i++)
9016 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9017 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9020 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9021 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9022 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);
9024 case Q3DEFORM_AUTOSPRITE2:
9025 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9026 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9027 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9028 VectorNormalize(newforward);
9029 VectorNormalize(newright);
9030 VectorNormalize(newup);
9031 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9032 // rsurface.batchvertex3f_vertexbuffer = NULL;
9033 // rsurface.batchvertex3f_bufferoffset = 0;
9035 const float *v1, *v2;
9045 memset(shortest, 0, sizeof(shortest));
9046 // a single autosprite surface can contain multiple sprites...
9047 for (j = 0;j < batchnumvertices - 3;j += 4)
9049 VectorClear(center);
9050 for (i = 0;i < 4;i++)
9051 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9052 VectorScale(center, 0.25f, center);
9053 // find the two shortest edges, then use them to define the
9054 // axis vectors for rotating around the central axis
9055 for (i = 0;i < 6;i++)
9057 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9058 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9059 l = VectorDistance2(v1, v2);
9060 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9062 l += (1.0f / 1024.0f);
9063 if (shortest[0].length2 > l || i == 0)
9065 shortest[1] = shortest[0];
9066 shortest[0].length2 = l;
9067 shortest[0].v1 = v1;
9068 shortest[0].v2 = v2;
9070 else if (shortest[1].length2 > l || i == 1)
9072 shortest[1].length2 = l;
9073 shortest[1].v1 = v1;
9074 shortest[1].v2 = v2;
9077 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9078 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9079 // this calculates the right vector from the shortest edge
9080 // and the up vector from the edge midpoints
9081 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9082 VectorNormalize(right);
9083 VectorSubtract(end, start, up);
9084 VectorNormalize(up);
9085 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9086 VectorSubtract(rsurface.localvieworigin, center, forward);
9087 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9088 VectorNegate(forward, forward);
9089 VectorReflect(forward, 0, up, forward);
9090 VectorNormalize(forward);
9091 CrossProduct(up, forward, newright);
9092 VectorNormalize(newright);
9093 // rotate the quad around the up axis vector, this is made
9094 // especially easy by the fact we know the quad is flat,
9095 // so we only have to subtract the center position and
9096 // measure distance along the right vector, and then
9097 // multiply that by the newright vector and add back the
9099 // we also need to subtract the old position to undo the
9100 // displacement from the center, which we do with a
9101 // DotProduct, the subtraction/addition of center is also
9102 // optimized into DotProducts here
9103 l = DotProduct(right, center);
9104 for (i = 0;i < 4;i++)
9106 v1 = rsurface.batchvertex3f + 3*(j+i);
9107 f = DotProduct(right, v1) - l;
9108 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9112 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9114 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9115 // rsurface.batchnormal3f_vertexbuffer = NULL;
9116 // rsurface.batchnormal3f_bufferoffset = 0;
9117 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9119 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9121 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9122 // rsurface.batchsvector3f_vertexbuffer = NULL;
9123 // rsurface.batchsvector3f_bufferoffset = 0;
9124 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9125 // rsurface.batchtvector3f_vertexbuffer = NULL;
9126 // rsurface.batchtvector3f_bufferoffset = 0;
9127 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);
9130 case Q3DEFORM_NORMAL:
9131 // deform the normals to make reflections wavey
9132 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9133 rsurface.batchnormal3f_vertexbuffer = NULL;
9134 rsurface.batchnormal3f_bufferoffset = 0;
9135 for (j = 0;j < batchnumvertices;j++)
9138 float *normal = rsurface.batchnormal3f + 3*j;
9139 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9140 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9141 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9142 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9143 VectorNormalize(normal);
9145 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9147 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9148 // rsurface.batchsvector3f_vertexbuffer = NULL;
9149 // rsurface.batchsvector3f_bufferoffset = 0;
9150 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9151 // rsurface.batchtvector3f_vertexbuffer = NULL;
9152 // rsurface.batchtvector3f_bufferoffset = 0;
9153 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);
9157 // deform vertex array to make wavey water and flags and such
9158 waveparms[0] = deform->waveparms[0];
9159 waveparms[1] = deform->waveparms[1];
9160 waveparms[2] = deform->waveparms[2];
9161 waveparms[3] = deform->waveparms[3];
9162 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9163 break; // if wavefunc is a nop, don't make a dynamic vertex array
9164 // this is how a divisor of vertex influence on deformation
9165 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9166 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9167 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9168 // rsurface.batchvertex3f_vertexbuffer = NULL;
9169 // rsurface.batchvertex3f_bufferoffset = 0;
9170 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9171 // rsurface.batchnormal3f_vertexbuffer = NULL;
9172 // rsurface.batchnormal3f_bufferoffset = 0;
9173 for (j = 0;j < batchnumvertices;j++)
9175 // if the wavefunc depends on time, evaluate it per-vertex
9178 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9179 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9181 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9183 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9184 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9185 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9187 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9188 // rsurface.batchsvector3f_vertexbuffer = NULL;
9189 // rsurface.batchsvector3f_bufferoffset = 0;
9190 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9191 // rsurface.batchtvector3f_vertexbuffer = NULL;
9192 // rsurface.batchtvector3f_bufferoffset = 0;
9193 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);
9196 case Q3DEFORM_BULGE:
9197 // deform vertex array to make the surface have moving bulges
9198 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9199 // rsurface.batchvertex3f_vertexbuffer = NULL;
9200 // rsurface.batchvertex3f_bufferoffset = 0;
9201 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9202 // rsurface.batchnormal3f_vertexbuffer = NULL;
9203 // rsurface.batchnormal3f_bufferoffset = 0;
9204 for (j = 0;j < batchnumvertices;j++)
9206 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9207 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9209 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9210 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9211 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9213 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9214 // rsurface.batchsvector3f_vertexbuffer = NULL;
9215 // rsurface.batchsvector3f_bufferoffset = 0;
9216 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9217 // rsurface.batchtvector3f_vertexbuffer = NULL;
9218 // rsurface.batchtvector3f_bufferoffset = 0;
9219 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);
9223 // deform vertex array
9224 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9225 break; // if wavefunc is a nop, don't make a dynamic vertex array
9226 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9227 VectorScale(deform->parms, scale, waveparms);
9228 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9229 // rsurface.batchvertex3f_vertexbuffer = NULL;
9230 // rsurface.batchvertex3f_bufferoffset = 0;
9231 for (j = 0;j < batchnumvertices;j++)
9232 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9237 // generate texcoords based on the chosen texcoord source
9238 switch(rsurface.texture->tcgen.tcgen)
9241 case Q3TCGEN_TEXTURE:
9243 case Q3TCGEN_LIGHTMAP:
9244 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9245 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9246 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9247 if (rsurface.batchtexcoordlightmap2f)
9248 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9250 case Q3TCGEN_VECTOR:
9251 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9252 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9253 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9254 for (j = 0;j < batchnumvertices;j++)
9256 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9257 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9260 case Q3TCGEN_ENVIRONMENT:
9261 // make environment reflections using a spheremap
9262 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9263 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9264 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9265 for (j = 0;j < batchnumvertices;j++)
9267 // identical to Q3A's method, but executed in worldspace so
9268 // carried models can be shiny too
9270 float viewer[3], d, reflected[3], worldreflected[3];
9272 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9273 // VectorNormalize(viewer);
9275 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9277 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9278 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9279 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9280 // note: this is proportinal to viewer, so we can normalize later
9282 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9283 VectorNormalize(worldreflected);
9285 // note: this sphere map only uses world x and z!
9286 // so positive and negative y will LOOK THE SAME.
9287 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9288 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9292 // the only tcmod that needs software vertex processing is turbulent, so
9293 // check for it here and apply the changes if needed
9294 // and we only support that as the first one
9295 // (handling a mixture of turbulent and other tcmods would be problematic
9296 // without punting it entirely to a software path)
9297 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9299 amplitude = rsurface.texture->tcmods[0].parms[1];
9300 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9301 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9302 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9303 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9304 for (j = 0;j < batchnumvertices;j++)
9306 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);
9307 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9311 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9313 // convert the modified arrays to vertex structs
9314 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9315 // rsurface.batchvertexmeshbuffer = NULL;
9316 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9317 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9318 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9319 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9320 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9321 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9322 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9324 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9326 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9327 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9330 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9331 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9332 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9333 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9334 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9335 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9336 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9337 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9338 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9342 void RSurf_DrawBatch(void)
9344 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9345 // through the pipeline, killing it earlier in the pipeline would have
9346 // per-surface overhead rather than per-batch overhead, so it's best to
9347 // reject it here, before it hits glDraw.
9348 if (rsurface.batchnumtriangles == 0)
9351 // batch debugging code
9352 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9358 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9359 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9362 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9364 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9366 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9367 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);
9374 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);
9377 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9379 // pick the closest matching water plane
9380 int planeindex, vertexindex, bestplaneindex = -1;
9384 r_waterstate_waterplane_t *p;
9385 qboolean prepared = false;
9387 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9389 if(p->camera_entity != rsurface.texture->camera_entity)
9394 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9396 if(rsurface.batchnumvertices == 0)
9399 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9401 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9402 d += fabs(PlaneDiff(vert, &p->plane));
9404 if (bestd > d || bestplaneindex < 0)
9407 bestplaneindex = planeindex;
9410 return bestplaneindex;
9411 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9412 // this situation though, as it might be better to render single larger
9413 // batches with useless stuff (backface culled for example) than to
9414 // render multiple smaller batches
9417 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9420 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9421 rsurface.passcolor4f_vertexbuffer = 0;
9422 rsurface.passcolor4f_bufferoffset = 0;
9423 for (i = 0;i < rsurface.batchnumvertices;i++)
9424 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9427 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9434 if (rsurface.passcolor4f)
9436 // generate color arrays
9437 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9438 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9439 rsurface.passcolor4f_vertexbuffer = 0;
9440 rsurface.passcolor4f_bufferoffset = 0;
9441 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)
9443 f = RSurf_FogVertex(v);
9452 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9453 rsurface.passcolor4f_vertexbuffer = 0;
9454 rsurface.passcolor4f_bufferoffset = 0;
9455 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9457 f = RSurf_FogVertex(v);
9466 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9473 if (!rsurface.passcolor4f)
9475 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9476 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9477 rsurface.passcolor4f_vertexbuffer = 0;
9478 rsurface.passcolor4f_bufferoffset = 0;
9479 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)
9481 f = RSurf_FogVertex(v);
9482 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9483 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9484 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9489 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9494 if (!rsurface.passcolor4f)
9496 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9497 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9498 rsurface.passcolor4f_vertexbuffer = 0;
9499 rsurface.passcolor4f_bufferoffset = 0;
9500 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9509 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9514 if (!rsurface.passcolor4f)
9516 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9517 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9518 rsurface.passcolor4f_vertexbuffer = 0;
9519 rsurface.passcolor4f_bufferoffset = 0;
9520 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9522 c2[0] = c[0] + r_refdef.scene.ambient;
9523 c2[1] = c[1] + r_refdef.scene.ambient;
9524 c2[2] = c[2] + r_refdef.scene.ambient;
9529 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9532 rsurface.passcolor4f = NULL;
9533 rsurface.passcolor4f_vertexbuffer = 0;
9534 rsurface.passcolor4f_bufferoffset = 0;
9535 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9536 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9537 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9538 GL_Color(r, g, b, a);
9539 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9543 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9545 // TODO: optimize applyfog && applycolor case
9546 // just apply fog if necessary, and tint the fog color array if necessary
9547 rsurface.passcolor4f = NULL;
9548 rsurface.passcolor4f_vertexbuffer = 0;
9549 rsurface.passcolor4f_bufferoffset = 0;
9550 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9551 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9552 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9553 GL_Color(r, g, b, a);
9557 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9560 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9561 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9562 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9563 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9564 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9565 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9566 GL_Color(r, g, b, a);
9570 static void RSurf_DrawBatch_GL11_ClampColor(void)
9575 if (!rsurface.passcolor4f)
9577 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9579 c2[0] = bound(0.0f, c1[0], 1.0f);
9580 c2[1] = bound(0.0f, c1[1], 1.0f);
9581 c2[2] = bound(0.0f, c1[2], 1.0f);
9582 c2[3] = bound(0.0f, c1[3], 1.0f);
9586 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9596 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9597 rsurface.passcolor4f_vertexbuffer = 0;
9598 rsurface.passcolor4f_bufferoffset = 0;
9599 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)
9601 f = -DotProduct(r_refdef.view.forward, n);
9603 f = f * 0.85 + 0.15; // work around so stuff won't get black
9604 f *= r_refdef.lightmapintensity;
9605 Vector4Set(c, f, f, f, 1);
9609 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9611 RSurf_DrawBatch_GL11_ApplyFakeLight();
9612 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9613 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9614 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9615 GL_Color(r, g, b, a);
9619 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9627 vec3_t ambientcolor;
9628 vec3_t diffusecolor;
9632 VectorCopy(rsurface.modellight_lightdir, lightdir);
9633 f = 0.5f * r_refdef.lightmapintensity;
9634 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9635 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9636 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9637 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9638 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9639 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9641 if (VectorLength2(diffusecolor) > 0)
9643 // q3-style directional shading
9644 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9645 rsurface.passcolor4f_vertexbuffer = 0;
9646 rsurface.passcolor4f_bufferoffset = 0;
9647 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)
9649 if ((f = DotProduct(n, lightdir)) > 0)
9650 VectorMA(ambientcolor, f, diffusecolor, c);
9652 VectorCopy(ambientcolor, c);
9659 *applycolor = false;
9663 *r = ambientcolor[0];
9664 *g = ambientcolor[1];
9665 *b = ambientcolor[2];
9666 rsurface.passcolor4f = NULL;
9667 rsurface.passcolor4f_vertexbuffer = 0;
9668 rsurface.passcolor4f_bufferoffset = 0;
9672 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9674 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9675 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9676 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9677 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9678 GL_Color(r, g, b, a);
9682 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9690 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9691 rsurface.passcolor4f_vertexbuffer = 0;
9692 rsurface.passcolor4f_bufferoffset = 0;
9694 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9696 f = 1 - RSurf_FogVertex(v);
9704 void RSurf_SetupDepthAndCulling(void)
9706 // submodels are biased to avoid z-fighting with world surfaces that they
9707 // may be exactly overlapping (avoids z-fighting artifacts on certain
9708 // doors and things in Quake maps)
9709 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9710 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9711 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9712 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9715 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9717 // transparent sky would be ridiculous
9718 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9720 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9721 skyrenderlater = true;
9722 RSurf_SetupDepthAndCulling();
9724 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9725 // skymasking on them, and Quake3 never did sky masking (unlike
9726 // software Quake and software Quake2), so disable the sky masking
9727 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9728 // and skymasking also looks very bad when noclipping outside the
9729 // level, so don't use it then either.
9730 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9732 R_Mesh_ResetTextureState();
9733 if (skyrendermasked)
9735 R_SetupShader_DepthOrShadow(false);
9736 // depth-only (masking)
9737 GL_ColorMask(0,0,0,0);
9738 // just to make sure that braindead drivers don't draw
9739 // anything despite that colormask...
9740 GL_BlendFunc(GL_ZERO, GL_ONE);
9741 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9742 if (rsurface.batchvertex3fbuffer)
9743 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9745 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9749 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9751 GL_BlendFunc(GL_ONE, GL_ZERO);
9752 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9753 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9754 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9757 if (skyrendermasked)
9758 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9760 R_Mesh_ResetTextureState();
9761 GL_Color(1, 1, 1, 1);
9764 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9765 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9766 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9768 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9772 // render screenspace normalmap to texture
9774 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9778 // bind lightmap texture
9780 // water/refraction/reflection/camera surfaces have to be handled specially
9781 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9783 int start, end, startplaneindex;
9784 for (start = 0;start < texturenumsurfaces;start = end)
9786 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9787 if(startplaneindex < 0)
9789 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9790 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9794 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9796 // now that we have a batch using the same planeindex, render it
9797 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9799 // render water or distortion background
9801 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), false);
9803 // blend surface on top
9804 GL_DepthMask(false);
9805 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9808 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9810 // render surface with reflection texture as input
9811 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9812 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), false);
9819 // render surface batch normally
9820 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9821 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
9825 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9827 // OpenGL 1.3 path - anything not completely ancient
9828 qboolean applycolor;
9831 const texturelayer_t *layer;
9832 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);
9833 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9835 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9838 int layertexrgbscale;
9839 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9841 if (layerindex == 0)
9845 GL_AlphaTest(false);
9846 GL_DepthFunc(GL_EQUAL);
9849 GL_DepthMask(layer->depthmask && writedepth);
9850 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9851 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9853 layertexrgbscale = 4;
9854 VectorScale(layer->color, 0.25f, layercolor);
9856 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9858 layertexrgbscale = 2;
9859 VectorScale(layer->color, 0.5f, layercolor);
9863 layertexrgbscale = 1;
9864 VectorScale(layer->color, 1.0f, layercolor);
9866 layercolor[3] = layer->color[3];
9867 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9868 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9869 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9870 switch (layer->type)
9872 case TEXTURELAYERTYPE_LITTEXTURE:
9873 // single-pass lightmapped texture with 2x rgbscale
9874 R_Mesh_TexBind(0, r_texture_white);
9875 R_Mesh_TexMatrix(0, NULL);
9876 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9877 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9878 R_Mesh_TexBind(1, layer->texture);
9879 R_Mesh_TexMatrix(1, &layer->texmatrix);
9880 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9881 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9882 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9883 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9884 else if (FAKELIGHT_ENABLED)
9885 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9886 else if (rsurface.uselightmaptexture)
9887 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9889 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9891 case TEXTURELAYERTYPE_TEXTURE:
9892 // singletexture unlit texture with transparency support
9893 R_Mesh_TexBind(0, layer->texture);
9894 R_Mesh_TexMatrix(0, &layer->texmatrix);
9895 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9896 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9897 R_Mesh_TexBind(1, 0);
9898 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9899 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9901 case TEXTURELAYERTYPE_FOG:
9902 // singletexture fogging
9905 R_Mesh_TexBind(0, layer->texture);
9906 R_Mesh_TexMatrix(0, &layer->texmatrix);
9907 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9908 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9912 R_Mesh_TexBind(0, 0);
9913 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9915 R_Mesh_TexBind(1, 0);
9916 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9917 // generate a color array for the fog pass
9918 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9919 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9923 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9926 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9928 GL_DepthFunc(GL_LEQUAL);
9929 GL_AlphaTest(false);
9933 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9935 // OpenGL 1.1 - crusty old voodoo path
9938 const texturelayer_t *layer;
9939 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);
9940 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9942 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9944 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9946 if (layerindex == 0)
9950 GL_AlphaTest(false);
9951 GL_DepthFunc(GL_EQUAL);
9954 GL_DepthMask(layer->depthmask && writedepth);
9955 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9956 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9957 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9958 switch (layer->type)
9960 case TEXTURELAYERTYPE_LITTEXTURE:
9961 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9963 // two-pass lit texture with 2x rgbscale
9964 // first the lightmap pass
9965 R_Mesh_TexBind(0, r_texture_white);
9966 R_Mesh_TexMatrix(0, NULL);
9967 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9968 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9969 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9970 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9971 else if (FAKELIGHT_ENABLED)
9972 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9973 else if (rsurface.uselightmaptexture)
9974 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9976 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9977 // then apply the texture to it
9978 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9979 R_Mesh_TexBind(0, layer->texture);
9980 R_Mesh_TexMatrix(0, &layer->texmatrix);
9981 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9982 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9983 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);
9987 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9988 R_Mesh_TexBind(0, layer->texture);
9989 R_Mesh_TexMatrix(0, &layer->texmatrix);
9990 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9991 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9992 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9993 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);
9995 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);
9998 case TEXTURELAYERTYPE_TEXTURE:
9999 // singletexture unlit texture with transparency support
10000 R_Mesh_TexBind(0, layer->texture);
10001 R_Mesh_TexMatrix(0, &layer->texmatrix);
10002 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10003 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10004 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);
10006 case TEXTURELAYERTYPE_FOG:
10007 // singletexture fogging
10008 if (layer->texture)
10010 R_Mesh_TexBind(0, layer->texture);
10011 R_Mesh_TexMatrix(0, &layer->texmatrix);
10012 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10013 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10017 R_Mesh_TexBind(0, 0);
10018 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10020 // generate a color array for the fog pass
10021 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10022 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10026 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10029 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10031 GL_DepthFunc(GL_LEQUAL);
10032 GL_AlphaTest(false);
10036 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10040 r_vertexgeneric_t *batchvertex;
10043 // R_Mesh_ResetTextureState();
10044 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10046 if(rsurface.texture && rsurface.texture->currentskinframe)
10048 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10049 c[3] *= rsurface.texture->currentalpha;
10059 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10061 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10062 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10063 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10066 // brighten it up (as texture value 127 means "unlit")
10067 c[0] *= 2 * r_refdef.view.colorscale;
10068 c[1] *= 2 * r_refdef.view.colorscale;
10069 c[2] *= 2 * r_refdef.view.colorscale;
10071 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10072 c[3] *= r_wateralpha.value;
10074 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10076 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10077 GL_DepthMask(false);
10079 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10081 GL_BlendFunc(GL_ONE, GL_ONE);
10082 GL_DepthMask(false);
10084 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10086 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10087 GL_DepthMask(false);
10089 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10091 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10092 GL_DepthMask(false);
10096 GL_BlendFunc(GL_ONE, GL_ZERO);
10097 GL_DepthMask(writedepth);
10100 if (r_showsurfaces.integer == 3)
10102 rsurface.passcolor4f = NULL;
10104 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10106 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10108 rsurface.passcolor4f = NULL;
10109 rsurface.passcolor4f_vertexbuffer = 0;
10110 rsurface.passcolor4f_bufferoffset = 0;
10112 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10114 qboolean applycolor = true;
10117 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10119 r_refdef.lightmapintensity = 1;
10120 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10121 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10123 else if (FAKELIGHT_ENABLED)
10125 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10127 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10128 RSurf_DrawBatch_GL11_ApplyFakeLight();
10129 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10133 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10135 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10136 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10137 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10140 if(!rsurface.passcolor4f)
10141 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10143 RSurf_DrawBatch_GL11_ApplyAmbient();
10144 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10145 if(r_refdef.fogenabled)
10146 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10147 RSurf_DrawBatch_GL11_ClampColor();
10149 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10150 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10153 else if (!r_refdef.view.showdebug)
10155 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10156 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10157 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10159 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10160 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10162 R_Mesh_PrepareVertices_Generic_Unlock();
10165 else if (r_showsurfaces.integer == 4)
10167 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10168 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10169 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10171 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10172 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10173 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10175 R_Mesh_PrepareVertices_Generic_Unlock();
10178 else if (r_showsurfaces.integer == 2)
10181 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10182 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10183 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10185 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10186 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10187 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10188 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10189 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10190 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10191 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10193 R_Mesh_PrepareVertices_Generic_Unlock();
10194 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10198 int texturesurfaceindex;
10200 const msurface_t *surface;
10201 float surfacecolor4f[4];
10202 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10203 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10205 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10207 surface = texturesurfacelist[texturesurfaceindex];
10208 k = (int)(((size_t)surface) / sizeof(msurface_t));
10209 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10210 for (j = 0;j < surface->num_vertices;j++)
10212 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10213 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10217 R_Mesh_PrepareVertices_Generic_Unlock();
10222 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10225 RSurf_SetupDepthAndCulling();
10226 if (r_showsurfaces.integer)
10228 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10231 switch (vid.renderpath)
10233 case RENDERPATH_GL20:
10234 case RENDERPATH_D3D9:
10235 case RENDERPATH_D3D10:
10236 case RENDERPATH_D3D11:
10237 case RENDERPATH_SOFT:
10238 case RENDERPATH_GLES2:
10239 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10241 case RENDERPATH_GL13:
10242 case RENDERPATH_GLES1:
10243 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10245 case RENDERPATH_GL11:
10246 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10252 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10255 RSurf_SetupDepthAndCulling();
10256 if (r_showsurfaces.integer)
10258 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10261 switch (vid.renderpath)
10263 case RENDERPATH_GL20:
10264 case RENDERPATH_D3D9:
10265 case RENDERPATH_D3D10:
10266 case RENDERPATH_D3D11:
10267 case RENDERPATH_SOFT:
10268 case RENDERPATH_GLES2:
10269 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10271 case RENDERPATH_GL13:
10272 case RENDERPATH_GLES1:
10273 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10275 case RENDERPATH_GL11:
10276 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10282 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10285 int texturenumsurfaces, endsurface;
10286 texture_t *texture;
10287 const msurface_t *surface;
10288 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10290 // if the model is static it doesn't matter what value we give for
10291 // wantnormals and wanttangents, so this logic uses only rules applicable
10292 // to a model, knowing that they are meaningless otherwise
10293 if (ent == r_refdef.scene.worldentity)
10294 RSurf_ActiveWorldEntity();
10295 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10296 RSurf_ActiveModelEntity(ent, false, false, false);
10299 switch (vid.renderpath)
10301 case RENDERPATH_GL20:
10302 case RENDERPATH_D3D9:
10303 case RENDERPATH_D3D10:
10304 case RENDERPATH_D3D11:
10305 case RENDERPATH_SOFT:
10306 case RENDERPATH_GLES2:
10307 RSurf_ActiveModelEntity(ent, true, true, false);
10309 case RENDERPATH_GL11:
10310 case RENDERPATH_GL13:
10311 case RENDERPATH_GLES1:
10312 RSurf_ActiveModelEntity(ent, true, false, false);
10317 if (r_transparentdepthmasking.integer)
10319 qboolean setup = false;
10320 for (i = 0;i < numsurfaces;i = j)
10323 surface = rsurface.modelsurfaces + surfacelist[i];
10324 texture = surface->texture;
10325 rsurface.texture = R_GetCurrentTexture(texture);
10326 rsurface.lightmaptexture = NULL;
10327 rsurface.deluxemaptexture = NULL;
10328 rsurface.uselightmaptexture = false;
10329 // scan ahead until we find a different texture
10330 endsurface = min(i + 1024, numsurfaces);
10331 texturenumsurfaces = 0;
10332 texturesurfacelist[texturenumsurfaces++] = surface;
10333 for (;j < endsurface;j++)
10335 surface = rsurface.modelsurfaces + surfacelist[j];
10336 if (texture != surface->texture)
10338 texturesurfacelist[texturenumsurfaces++] = surface;
10340 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10342 // render the range of surfaces as depth
10346 GL_ColorMask(0,0,0,0);
10348 GL_DepthTest(true);
10349 GL_BlendFunc(GL_ONE, GL_ZERO);
10350 GL_DepthMask(true);
10351 // R_Mesh_ResetTextureState();
10352 R_SetupShader_DepthOrShadow(false);
10354 RSurf_SetupDepthAndCulling();
10355 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10356 if (rsurface.batchvertex3fbuffer)
10357 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10359 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10363 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10366 for (i = 0;i < numsurfaces;i = j)
10369 surface = rsurface.modelsurfaces + surfacelist[i];
10370 texture = surface->texture;
10371 rsurface.texture = R_GetCurrentTexture(texture);
10372 // scan ahead until we find a different texture
10373 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10374 texturenumsurfaces = 0;
10375 texturesurfacelist[texturenumsurfaces++] = surface;
10376 if(FAKELIGHT_ENABLED)
10378 rsurface.lightmaptexture = NULL;
10379 rsurface.deluxemaptexture = NULL;
10380 rsurface.uselightmaptexture = false;
10381 for (;j < endsurface;j++)
10383 surface = rsurface.modelsurfaces + surfacelist[j];
10384 if (texture != surface->texture)
10386 texturesurfacelist[texturenumsurfaces++] = surface;
10391 rsurface.lightmaptexture = surface->lightmaptexture;
10392 rsurface.deluxemaptexture = surface->deluxemaptexture;
10393 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10394 for (;j < endsurface;j++)
10396 surface = rsurface.modelsurfaces + surfacelist[j];
10397 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10399 texturesurfacelist[texturenumsurfaces++] = surface;
10402 // render the range of surfaces
10403 if (ent == r_refdef.scene.worldentity)
10404 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10406 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10408 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10411 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10413 // transparent surfaces get pushed off into the transparent queue
10414 int surfacelistindex;
10415 const msurface_t *surface;
10416 vec3_t tempcenter, center;
10417 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10419 surface = texturesurfacelist[surfacelistindex];
10420 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10421 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10422 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10423 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10424 if (queueentity->transparent_offset) // transparent offset
10426 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10427 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10428 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10430 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10434 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10436 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10438 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10440 RSurf_SetupDepthAndCulling();
10441 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10442 if (rsurface.batchvertex3fbuffer)
10443 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10445 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10449 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10451 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10454 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10457 if (!rsurface.texture->currentnumlayers)
10459 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10460 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10462 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10464 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10465 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10466 else if (!rsurface.texture->currentnumlayers)
10468 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10470 // in the deferred case, transparent surfaces were queued during prepass
10471 if (!r_shadow_usingdeferredprepass)
10472 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10476 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10477 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10482 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10485 texture_t *texture;
10486 R_FrameData_SetMark();
10487 // break the surface list down into batches by texture and use of lightmapping
10488 for (i = 0;i < numsurfaces;i = j)
10491 // texture is the base texture pointer, rsurface.texture is the
10492 // current frame/skin the texture is directing us to use (for example
10493 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10494 // use skin 1 instead)
10495 texture = surfacelist[i]->texture;
10496 rsurface.texture = R_GetCurrentTexture(texture);
10497 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10499 // if this texture is not the kind we want, skip ahead to the next one
10500 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10504 if(FAKELIGHT_ENABLED || depthonly || prepass)
10506 rsurface.lightmaptexture = NULL;
10507 rsurface.deluxemaptexture = NULL;
10508 rsurface.uselightmaptexture = false;
10509 // simply scan ahead until we find a different texture or lightmap state
10510 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10515 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10516 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10517 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10518 // simply scan ahead until we find a different texture or lightmap state
10519 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10522 // render the range of surfaces
10523 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10525 R_FrameData_ReturnToMark();
10528 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10532 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10535 if (!rsurface.texture->currentnumlayers)
10537 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10538 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10540 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10542 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10543 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10544 else if (!rsurface.texture->currentnumlayers)
10546 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10548 // in the deferred case, transparent surfaces were queued during prepass
10549 if (!r_shadow_usingdeferredprepass)
10550 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10554 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10555 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10560 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10563 texture_t *texture;
10564 R_FrameData_SetMark();
10565 // break the surface list down into batches by texture and use of lightmapping
10566 for (i = 0;i < numsurfaces;i = j)
10569 // texture is the base texture pointer, rsurface.texture is the
10570 // current frame/skin the texture is directing us to use (for example
10571 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10572 // use skin 1 instead)
10573 texture = surfacelist[i]->texture;
10574 rsurface.texture = R_GetCurrentTexture(texture);
10575 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10577 // if this texture is not the kind we want, skip ahead to the next one
10578 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10582 if(FAKELIGHT_ENABLED || depthonly || prepass)
10584 rsurface.lightmaptexture = NULL;
10585 rsurface.deluxemaptexture = NULL;
10586 rsurface.uselightmaptexture = false;
10587 // simply scan ahead until we find a different texture or lightmap state
10588 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10593 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10594 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10595 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10596 // simply scan ahead until we find a different texture or lightmap state
10597 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10600 // render the range of surfaces
10601 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10603 R_FrameData_ReturnToMark();
10606 float locboxvertex3f[6*4*3] =
10608 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10609 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10610 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10611 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10612 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10613 1,0,0, 0,0,0, 0,1,0, 1,1,0
10616 unsigned short locboxelements[6*2*3] =
10621 12,13,14, 12,14,15,
10622 16,17,18, 16,18,19,
10626 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10629 cl_locnode_t *loc = (cl_locnode_t *)ent;
10631 float vertex3f[6*4*3];
10633 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10634 GL_DepthMask(false);
10635 GL_DepthRange(0, 1);
10636 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10637 GL_DepthTest(true);
10638 GL_CullFace(GL_NONE);
10639 R_EntityMatrix(&identitymatrix);
10641 // R_Mesh_ResetTextureState();
10643 i = surfacelist[0];
10644 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10645 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10646 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10647 surfacelist[0] < 0 ? 0.5f : 0.125f);
10649 if (VectorCompare(loc->mins, loc->maxs))
10651 VectorSet(size, 2, 2, 2);
10652 VectorMA(loc->mins, -0.5f, size, mins);
10656 VectorCopy(loc->mins, mins);
10657 VectorSubtract(loc->maxs, loc->mins, size);
10660 for (i = 0;i < 6*4*3;)
10661 for (j = 0;j < 3;j++, i++)
10662 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10664 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10665 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10666 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10669 void R_DrawLocs(void)
10672 cl_locnode_t *loc, *nearestloc;
10674 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10675 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10677 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10678 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10682 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10684 if (decalsystem->decals)
10685 Mem_Free(decalsystem->decals);
10686 memset(decalsystem, 0, sizeof(*decalsystem));
10689 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)
10692 tridecal_t *decals;
10695 // expand or initialize the system
10696 if (decalsystem->maxdecals <= decalsystem->numdecals)
10698 decalsystem_t old = *decalsystem;
10699 qboolean useshortelements;
10700 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10701 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10702 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)));
10703 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10704 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10705 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10706 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10707 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10708 if (decalsystem->numdecals)
10709 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10711 Mem_Free(old.decals);
10712 for (i = 0;i < decalsystem->maxdecals*3;i++)
10713 decalsystem->element3i[i] = i;
10714 if (useshortelements)
10715 for (i = 0;i < decalsystem->maxdecals*3;i++)
10716 decalsystem->element3s[i] = i;
10719 // grab a decal and search for another free slot for the next one
10720 decals = decalsystem->decals;
10721 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10722 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10724 decalsystem->freedecal = i;
10725 if (decalsystem->numdecals <= i)
10726 decalsystem->numdecals = i + 1;
10728 // initialize the decal
10730 decal->triangleindex = triangleindex;
10731 decal->surfaceindex = surfaceindex;
10732 decal->decalsequence = decalsequence;
10733 decal->color4f[0][0] = c0[0];
10734 decal->color4f[0][1] = c0[1];
10735 decal->color4f[0][2] = c0[2];
10736 decal->color4f[0][3] = 1;
10737 decal->color4f[1][0] = c1[0];
10738 decal->color4f[1][1] = c1[1];
10739 decal->color4f[1][2] = c1[2];
10740 decal->color4f[1][3] = 1;
10741 decal->color4f[2][0] = c2[0];
10742 decal->color4f[2][1] = c2[1];
10743 decal->color4f[2][2] = c2[2];
10744 decal->color4f[2][3] = 1;
10745 decal->vertex3f[0][0] = v0[0];
10746 decal->vertex3f[0][1] = v0[1];
10747 decal->vertex3f[0][2] = v0[2];
10748 decal->vertex3f[1][0] = v1[0];
10749 decal->vertex3f[1][1] = v1[1];
10750 decal->vertex3f[1][2] = v1[2];
10751 decal->vertex3f[2][0] = v2[0];
10752 decal->vertex3f[2][1] = v2[1];
10753 decal->vertex3f[2][2] = v2[2];
10754 decal->texcoord2f[0][0] = t0[0];
10755 decal->texcoord2f[0][1] = t0[1];
10756 decal->texcoord2f[1][0] = t1[0];
10757 decal->texcoord2f[1][1] = t1[1];
10758 decal->texcoord2f[2][0] = t2[0];
10759 decal->texcoord2f[2][1] = t2[1];
10760 TriangleNormal(v0, v1, v2, decal->plane);
10761 VectorNormalize(decal->plane);
10762 decal->plane[3] = DotProduct(v0, decal->plane);
10765 extern cvar_t cl_decals_bias;
10766 extern cvar_t cl_decals_models;
10767 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10768 // baseparms, parms, temps
10769 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)
10774 const float *vertex3f;
10775 const float *normal3f;
10777 float points[2][9][3];
10784 e = rsurface.modelelement3i + 3*triangleindex;
10786 vertex3f = rsurface.modelvertex3f;
10787 normal3f = rsurface.modelnormal3f;
10791 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10793 index = 3*e[cornerindex];
10794 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10799 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10801 index = 3*e[cornerindex];
10802 VectorCopy(vertex3f + index, v[cornerindex]);
10807 //TriangleNormal(v[0], v[1], v[2], normal);
10808 //if (DotProduct(normal, localnormal) < 0.0f)
10810 // clip by each of the box planes formed from the projection matrix
10811 // if anything survives, we emit the decal
10812 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]);
10815 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]);
10818 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]);
10821 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]);
10824 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]);
10827 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]);
10830 // some part of the triangle survived, so we have to accept it...
10833 // dynamic always uses the original triangle
10835 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10837 index = 3*e[cornerindex];
10838 VectorCopy(vertex3f + index, v[cornerindex]);
10841 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10843 // convert vertex positions to texcoords
10844 Matrix4x4_Transform(projection, v[cornerindex], temp);
10845 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10846 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10847 // calculate distance fade from the projection origin
10848 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10849 f = bound(0.0f, f, 1.0f);
10850 c[cornerindex][0] = r * f;
10851 c[cornerindex][1] = g * f;
10852 c[cornerindex][2] = b * f;
10853 c[cornerindex][3] = 1.0f;
10854 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10857 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);
10859 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10860 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);
10862 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)
10864 matrix4x4_t projection;
10865 decalsystem_t *decalsystem;
10868 const msurface_t *surface;
10869 const msurface_t *surfaces;
10870 const int *surfacelist;
10871 const texture_t *texture;
10873 int numsurfacelist;
10874 int surfacelistindex;
10877 float localorigin[3];
10878 float localnormal[3];
10879 float localmins[3];
10880 float localmaxs[3];
10883 float planes[6][4];
10886 int bih_triangles_count;
10887 int bih_triangles[256];
10888 int bih_surfaces[256];
10890 decalsystem = &ent->decalsystem;
10891 model = ent->model;
10892 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10894 R_DecalSystem_Reset(&ent->decalsystem);
10898 if (!model->brush.data_leafs && !cl_decals_models.integer)
10900 if (decalsystem->model)
10901 R_DecalSystem_Reset(decalsystem);
10905 if (decalsystem->model != model)
10906 R_DecalSystem_Reset(decalsystem);
10907 decalsystem->model = model;
10909 RSurf_ActiveModelEntity(ent, true, false, false);
10911 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10912 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10913 VectorNormalize(localnormal);
10914 localsize = worldsize*rsurface.inversematrixscale;
10915 localmins[0] = localorigin[0] - localsize;
10916 localmins[1] = localorigin[1] - localsize;
10917 localmins[2] = localorigin[2] - localsize;
10918 localmaxs[0] = localorigin[0] + localsize;
10919 localmaxs[1] = localorigin[1] + localsize;
10920 localmaxs[2] = localorigin[2] + localsize;
10922 //VectorCopy(localnormal, planes[4]);
10923 //VectorVectors(planes[4], planes[2], planes[0]);
10924 AnglesFromVectors(angles, localnormal, NULL, false);
10925 AngleVectors(angles, planes[0], planes[2], planes[4]);
10926 VectorNegate(planes[0], planes[1]);
10927 VectorNegate(planes[2], planes[3]);
10928 VectorNegate(planes[4], planes[5]);
10929 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10930 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10931 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10932 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10933 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10934 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10939 matrix4x4_t forwardprojection;
10940 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10941 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10946 float projectionvector[4][3];
10947 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10948 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10949 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10950 projectionvector[0][0] = planes[0][0] * ilocalsize;
10951 projectionvector[0][1] = planes[1][0] * ilocalsize;
10952 projectionvector[0][2] = planes[2][0] * ilocalsize;
10953 projectionvector[1][0] = planes[0][1] * ilocalsize;
10954 projectionvector[1][1] = planes[1][1] * ilocalsize;
10955 projectionvector[1][2] = planes[2][1] * ilocalsize;
10956 projectionvector[2][0] = planes[0][2] * ilocalsize;
10957 projectionvector[2][1] = planes[1][2] * ilocalsize;
10958 projectionvector[2][2] = planes[2][2] * ilocalsize;
10959 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10960 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10961 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10962 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10966 dynamic = model->surfmesh.isanimated;
10967 numsurfacelist = model->nummodelsurfaces;
10968 surfacelist = model->sortedmodelsurfaces;
10969 surfaces = model->data_surfaces;
10972 bih_triangles_count = -1;
10975 if(model->render_bih.numleafs)
10976 bih = &model->render_bih;
10977 else if(model->collision_bih.numleafs)
10978 bih = &model->collision_bih;
10981 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10982 if(bih_triangles_count == 0)
10984 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10986 if(bih_triangles_count > 0)
10988 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10990 surfaceindex = bih_surfaces[triangleindex];
10991 surface = surfaces + surfaceindex;
10992 texture = surface->texture;
10993 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10995 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10997 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11002 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11004 surfaceindex = surfacelist[surfacelistindex];
11005 surface = surfaces + surfaceindex;
11006 // check cull box first because it rejects more than any other check
11007 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11009 // skip transparent surfaces
11010 texture = surface->texture;
11011 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11013 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11015 numtriangles = surface->num_triangles;
11016 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11017 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11022 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11023 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)
11025 int renderentityindex;
11026 float worldmins[3];
11027 float worldmaxs[3];
11028 entity_render_t *ent;
11030 if (!cl_decals_newsystem.integer)
11033 worldmins[0] = worldorigin[0] - worldsize;
11034 worldmins[1] = worldorigin[1] - worldsize;
11035 worldmins[2] = worldorigin[2] - worldsize;
11036 worldmaxs[0] = worldorigin[0] + worldsize;
11037 worldmaxs[1] = worldorigin[1] + worldsize;
11038 worldmaxs[2] = worldorigin[2] + worldsize;
11040 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11042 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11044 ent = r_refdef.scene.entities[renderentityindex];
11045 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11048 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11052 typedef struct r_decalsystem_splatqueue_s
11054 vec3_t worldorigin;
11055 vec3_t worldnormal;
11061 r_decalsystem_splatqueue_t;
11063 int r_decalsystem_numqueued = 0;
11064 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11066 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)
11068 r_decalsystem_splatqueue_t *queue;
11070 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11073 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11074 VectorCopy(worldorigin, queue->worldorigin);
11075 VectorCopy(worldnormal, queue->worldnormal);
11076 Vector4Set(queue->color, r, g, b, a);
11077 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11078 queue->worldsize = worldsize;
11079 queue->decalsequence = cl.decalsequence++;
11082 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11085 r_decalsystem_splatqueue_t *queue;
11087 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11088 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);
11089 r_decalsystem_numqueued = 0;
11092 extern cvar_t cl_decals_max;
11093 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11096 decalsystem_t *decalsystem = &ent->decalsystem;
11103 if (!decalsystem->numdecals)
11106 if (r_showsurfaces.integer)
11109 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11111 R_DecalSystem_Reset(decalsystem);
11115 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11116 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11118 if (decalsystem->lastupdatetime)
11119 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11122 decalsystem->lastupdatetime = r_refdef.scene.time;
11123 decal = decalsystem->decals;
11124 numdecals = decalsystem->numdecals;
11126 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11128 if (decal->color4f[0][3])
11130 decal->lived += frametime;
11131 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11133 memset(decal, 0, sizeof(*decal));
11134 if (decalsystem->freedecal > i)
11135 decalsystem->freedecal = i;
11139 decal = decalsystem->decals;
11140 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11143 // collapse the array by shuffling the tail decals into the gaps
11146 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11147 decalsystem->freedecal++;
11148 if (decalsystem->freedecal == numdecals)
11150 decal[decalsystem->freedecal] = decal[--numdecals];
11153 decalsystem->numdecals = numdecals;
11155 if (numdecals <= 0)
11157 // if there are no decals left, reset decalsystem
11158 R_DecalSystem_Reset(decalsystem);
11162 extern skinframe_t *decalskinframe;
11163 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11166 decalsystem_t *decalsystem = &ent->decalsystem;
11175 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11178 numdecals = decalsystem->numdecals;
11182 if (r_showsurfaces.integer)
11185 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11187 R_DecalSystem_Reset(decalsystem);
11191 // if the model is static it doesn't matter what value we give for
11192 // wantnormals and wanttangents, so this logic uses only rules applicable
11193 // to a model, knowing that they are meaningless otherwise
11194 if (ent == r_refdef.scene.worldentity)
11195 RSurf_ActiveWorldEntity();
11197 RSurf_ActiveModelEntity(ent, false, false, false);
11199 decalsystem->lastupdatetime = r_refdef.scene.time;
11200 decal = decalsystem->decals;
11202 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11204 // update vertex positions for animated models
11205 v3f = decalsystem->vertex3f;
11206 c4f = decalsystem->color4f;
11207 t2f = decalsystem->texcoord2f;
11208 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11210 if (!decal->color4f[0][3])
11213 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11217 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11220 // update color values for fading decals
11221 if (decal->lived >= cl_decals_time.value)
11222 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11226 c4f[ 0] = decal->color4f[0][0] * alpha;
11227 c4f[ 1] = decal->color4f[0][1] * alpha;
11228 c4f[ 2] = decal->color4f[0][2] * alpha;
11230 c4f[ 4] = decal->color4f[1][0] * alpha;
11231 c4f[ 5] = decal->color4f[1][1] * alpha;
11232 c4f[ 6] = decal->color4f[1][2] * alpha;
11234 c4f[ 8] = decal->color4f[2][0] * alpha;
11235 c4f[ 9] = decal->color4f[2][1] * alpha;
11236 c4f[10] = decal->color4f[2][2] * alpha;
11239 t2f[0] = decal->texcoord2f[0][0];
11240 t2f[1] = decal->texcoord2f[0][1];
11241 t2f[2] = decal->texcoord2f[1][0];
11242 t2f[3] = decal->texcoord2f[1][1];
11243 t2f[4] = decal->texcoord2f[2][0];
11244 t2f[5] = decal->texcoord2f[2][1];
11246 // update vertex positions for animated models
11247 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11249 e = rsurface.modelelement3i + 3*decal->triangleindex;
11250 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11251 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11252 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11256 VectorCopy(decal->vertex3f[0], v3f);
11257 VectorCopy(decal->vertex3f[1], v3f + 3);
11258 VectorCopy(decal->vertex3f[2], v3f + 6);
11261 if (r_refdef.fogenabled)
11263 alpha = RSurf_FogVertex(v3f);
11264 VectorScale(c4f, alpha, c4f);
11265 alpha = RSurf_FogVertex(v3f + 3);
11266 VectorScale(c4f + 4, alpha, c4f + 4);
11267 alpha = RSurf_FogVertex(v3f + 6);
11268 VectorScale(c4f + 8, alpha, c4f + 8);
11279 r_refdef.stats.drawndecals += numtris;
11281 // now render the decals all at once
11282 // (this assumes they all use one particle font texture!)
11283 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11284 // R_Mesh_ResetTextureState();
11285 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11286 GL_DepthMask(false);
11287 GL_DepthRange(0, 1);
11288 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11289 GL_DepthTest(true);
11290 GL_CullFace(GL_NONE);
11291 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11292 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11293 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11297 static void R_DrawModelDecals(void)
11301 // fade faster when there are too many decals
11302 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11303 for (i = 0;i < r_refdef.scene.numentities;i++)
11304 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11306 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11307 for (i = 0;i < r_refdef.scene.numentities;i++)
11308 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11309 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11311 R_DecalSystem_ApplySplatEntitiesQueue();
11313 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11314 for (i = 0;i < r_refdef.scene.numentities;i++)
11315 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11317 r_refdef.stats.totaldecals += numdecals;
11319 if (r_showsurfaces.integer)
11322 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11324 for (i = 0;i < r_refdef.scene.numentities;i++)
11326 if (!r_refdef.viewcache.entityvisible[i])
11328 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11329 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11333 extern cvar_t mod_collision_bih;
11334 void R_DrawDebugModel(void)
11336 entity_render_t *ent = rsurface.entity;
11337 int i, j, k, l, flagsmask;
11338 const msurface_t *surface;
11339 dp_model_t *model = ent->model;
11342 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11345 if (r_showoverdraw.value > 0)
11347 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11348 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11349 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11350 GL_DepthTest(false);
11351 GL_DepthMask(false);
11352 GL_DepthRange(0, 1);
11353 GL_BlendFunc(GL_ONE, GL_ONE);
11354 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11356 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11358 rsurface.texture = R_GetCurrentTexture(surface->texture);
11359 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11361 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11362 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11363 if (!rsurface.texture->currentlayers->depthmask)
11364 GL_Color(c, 0, 0, 1.0f);
11365 else if (ent == r_refdef.scene.worldentity)
11366 GL_Color(c, c, c, 1.0f);
11368 GL_Color(0, c, 0, 1.0f);
11369 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11373 rsurface.texture = NULL;
11376 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11378 // R_Mesh_ResetTextureState();
11379 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11380 GL_DepthRange(0, 1);
11381 GL_DepthTest(!r_showdisabledepthtest.integer);
11382 GL_DepthMask(false);
11383 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11385 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11389 qboolean cullbox = ent == r_refdef.scene.worldentity;
11390 const q3mbrush_t *brush;
11391 const bih_t *bih = &model->collision_bih;
11392 const bih_leaf_t *bihleaf;
11393 float vertex3f[3][3];
11394 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11396 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11398 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11400 switch (bihleaf->type)
11403 brush = model->brush.data_brushes + bihleaf->itemindex;
11404 if (brush->colbrushf && brush->colbrushf->numtriangles)
11406 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);
11407 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11408 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11411 case BIH_COLLISIONTRIANGLE:
11412 triangleindex = bihleaf->itemindex;
11413 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11414 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11415 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11416 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);
11417 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11418 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11420 case BIH_RENDERTRIANGLE:
11421 triangleindex = bihleaf->itemindex;
11422 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11423 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11424 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11425 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);
11426 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11427 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11433 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11436 if (r_showtris.integer && qglPolygonMode)
11438 if (r_showdisabledepthtest.integer)
11440 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11441 GL_DepthMask(false);
11445 GL_BlendFunc(GL_ONE, GL_ZERO);
11446 GL_DepthMask(true);
11448 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11449 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11451 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11453 rsurface.texture = R_GetCurrentTexture(surface->texture);
11454 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11456 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11457 if (!rsurface.texture->currentlayers->depthmask)
11458 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11459 else if (ent == r_refdef.scene.worldentity)
11460 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11462 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11463 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11467 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11468 rsurface.texture = NULL;
11471 if (r_shownormals.value != 0 && qglBegin)
11473 if (r_showdisabledepthtest.integer)
11475 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11476 GL_DepthMask(false);
11480 GL_BlendFunc(GL_ONE, GL_ZERO);
11481 GL_DepthMask(true);
11483 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11485 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11487 rsurface.texture = R_GetCurrentTexture(surface->texture);
11488 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11490 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11491 qglBegin(GL_LINES);
11492 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11494 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11496 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11497 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11498 qglVertex3f(v[0], v[1], v[2]);
11499 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11500 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11501 qglVertex3f(v[0], v[1], v[2]);
11504 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11506 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11508 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11509 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11510 qglVertex3f(v[0], v[1], v[2]);
11511 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11512 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11513 qglVertex3f(v[0], v[1], v[2]);
11516 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11518 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11520 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11521 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11522 qglVertex3f(v[0], v[1], v[2]);
11523 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11524 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11525 qglVertex3f(v[0], v[1], v[2]);
11528 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11530 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11532 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11533 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11534 qglVertex3f(v[0], v[1], v[2]);
11535 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11536 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11537 qglVertex3f(v[0], v[1], v[2]);
11544 rsurface.texture = NULL;
11549 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11550 int r_maxsurfacelist = 0;
11551 const msurface_t **r_surfacelist = NULL;
11552 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11554 int i, j, endj, flagsmask;
11555 dp_model_t *model = r_refdef.scene.worldmodel;
11556 msurface_t *surfaces;
11557 unsigned char *update;
11558 int numsurfacelist = 0;
11562 if (r_maxsurfacelist < model->num_surfaces)
11564 r_maxsurfacelist = model->num_surfaces;
11566 Mem_Free((msurface_t**)r_surfacelist);
11567 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11570 RSurf_ActiveWorldEntity();
11572 surfaces = model->data_surfaces;
11573 update = model->brushq1.lightmapupdateflags;
11575 // update light styles on this submodel
11576 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11578 model_brush_lightstyleinfo_t *style;
11579 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11581 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11583 int *list = style->surfacelist;
11584 style->value = r_refdef.scene.lightstylevalue[style->style];
11585 for (j = 0;j < style->numsurfaces;j++)
11586 update[list[j]] = true;
11591 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11595 R_DrawDebugModel();
11596 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11600 rsurface.lightmaptexture = NULL;
11601 rsurface.deluxemaptexture = NULL;
11602 rsurface.uselightmaptexture = false;
11603 rsurface.texture = NULL;
11604 rsurface.rtlight = NULL;
11605 numsurfacelist = 0;
11606 // add visible surfaces to draw list
11607 for (i = 0;i < model->nummodelsurfaces;i++)
11609 j = model->sortedmodelsurfaces[i];
11610 if (r_refdef.viewcache.world_surfacevisible[j])
11611 r_surfacelist[numsurfacelist++] = surfaces + j;
11613 // update lightmaps if needed
11614 if (model->brushq1.firstrender)
11616 model->brushq1.firstrender = false;
11617 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11619 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11623 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11624 if (r_refdef.viewcache.world_surfacevisible[j])
11626 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11628 // don't do anything if there were no surfaces
11629 if (!numsurfacelist)
11631 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11634 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11636 // add to stats if desired
11637 if (r_speeds.integer && !skysurfaces && !depthonly)
11639 r_refdef.stats.world_surfaces += numsurfacelist;
11640 for (j = 0;j < numsurfacelist;j++)
11641 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11644 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11647 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11649 int i, j, endj, flagsmask;
11650 dp_model_t *model = ent->model;
11651 msurface_t *surfaces;
11652 unsigned char *update;
11653 int numsurfacelist = 0;
11657 if (r_maxsurfacelist < model->num_surfaces)
11659 r_maxsurfacelist = model->num_surfaces;
11661 Mem_Free((msurface_t **)r_surfacelist);
11662 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11665 // if the model is static it doesn't matter what value we give for
11666 // wantnormals and wanttangents, so this logic uses only rules applicable
11667 // to a model, knowing that they are meaningless otherwise
11668 if (ent == r_refdef.scene.worldentity)
11669 RSurf_ActiveWorldEntity();
11670 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11671 RSurf_ActiveModelEntity(ent, false, false, false);
11673 RSurf_ActiveModelEntity(ent, true, true, true);
11674 else if (depthonly)
11676 switch (vid.renderpath)
11678 case RENDERPATH_GL20:
11679 case RENDERPATH_D3D9:
11680 case RENDERPATH_D3D10:
11681 case RENDERPATH_D3D11:
11682 case RENDERPATH_SOFT:
11683 case RENDERPATH_GLES2:
11684 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11686 case RENDERPATH_GL11:
11687 case RENDERPATH_GL13:
11688 case RENDERPATH_GLES1:
11689 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11695 switch (vid.renderpath)
11697 case RENDERPATH_GL20:
11698 case RENDERPATH_D3D9:
11699 case RENDERPATH_D3D10:
11700 case RENDERPATH_D3D11:
11701 case RENDERPATH_SOFT:
11702 case RENDERPATH_GLES2:
11703 RSurf_ActiveModelEntity(ent, true, true, false);
11705 case RENDERPATH_GL11:
11706 case RENDERPATH_GL13:
11707 case RENDERPATH_GLES1:
11708 RSurf_ActiveModelEntity(ent, true, false, false);
11713 surfaces = model->data_surfaces;
11714 update = model->brushq1.lightmapupdateflags;
11716 // update light styles
11717 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11719 model_brush_lightstyleinfo_t *style;
11720 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11722 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11724 int *list = style->surfacelist;
11725 style->value = r_refdef.scene.lightstylevalue[style->style];
11726 for (j = 0;j < style->numsurfaces;j++)
11727 update[list[j]] = true;
11732 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11736 R_DrawDebugModel();
11737 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11741 rsurface.lightmaptexture = NULL;
11742 rsurface.deluxemaptexture = NULL;
11743 rsurface.uselightmaptexture = false;
11744 rsurface.texture = NULL;
11745 rsurface.rtlight = NULL;
11746 numsurfacelist = 0;
11747 // add visible surfaces to draw list
11748 for (i = 0;i < model->nummodelsurfaces;i++)
11749 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11750 // don't do anything if there were no surfaces
11751 if (!numsurfacelist)
11753 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11756 // update lightmaps if needed
11760 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11765 R_BuildLightMap(ent, surfaces + j);
11770 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11772 R_BuildLightMap(ent, surfaces + j);
11773 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11775 // add to stats if desired
11776 if (r_speeds.integer && !skysurfaces && !depthonly)
11778 r_refdef.stats.entities_surfaces += numsurfacelist;
11779 for (j = 0;j < numsurfacelist;j++)
11780 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11783 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11786 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11788 static texture_t texture;
11789 static msurface_t surface;
11790 const msurface_t *surfacelist = &surface;
11792 // fake enough texture and surface state to render this geometry
11794 texture.update_lastrenderframe = -1; // regenerate this texture
11795 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11796 texture.currentskinframe = skinframe;
11797 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11798 texture.offsetmapping = OFFSETMAPPING_OFF;
11799 texture.offsetscale = 1;
11800 texture.specularscalemod = 1;
11801 texture.specularpowermod = 1;
11803 surface.texture = &texture;
11804 surface.num_triangles = numtriangles;
11805 surface.num_firsttriangle = firsttriangle;
11806 surface.num_vertices = numvertices;
11807 surface.num_firstvertex = firstvertex;
11810 rsurface.texture = R_GetCurrentTexture(surface.texture);
11811 rsurface.lightmaptexture = NULL;
11812 rsurface.deluxemaptexture = NULL;
11813 rsurface.uselightmaptexture = false;
11814 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11817 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)
11819 static msurface_t surface;
11820 const msurface_t *surfacelist = &surface;
11822 // fake enough texture and surface state to render this geometry
11823 surface.texture = texture;
11824 surface.num_triangles = numtriangles;
11825 surface.num_firsttriangle = firsttriangle;
11826 surface.num_vertices = numvertices;
11827 surface.num_firstvertex = firstvertex;
11830 rsurface.texture = R_GetCurrentTexture(surface.texture);
11831 rsurface.lightmaptexture = NULL;
11832 rsurface.deluxemaptexture = NULL;
11833 rsurface.uselightmaptexture = false;
11834 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);