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 - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 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 - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 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 - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 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 - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 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 - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 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) - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 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) - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 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) - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 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) && 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;
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( item->base == NULL )
3208 rtexture_t *dyntexture;
3209 // check whether its a dynamic texture
3210 // 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]
3211 dyntexture = CL_GetDynTexture( basename );
3212 item->base = dyntexture; // either NULL or dyntexture handle
3215 R_SkinFrame_MarkUsed(item);
3219 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3221 unsigned long long avgcolor[5], wsum; \
3229 for(pix = 0; pix < cnt; ++pix) \
3232 for(comp = 0; comp < 3; ++comp) \
3234 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3237 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3239 for(comp = 0; comp < 3; ++comp) \
3240 avgcolor[comp] += getpixel * w; \
3243 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3244 avgcolor[4] += getpixel; \
3246 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3248 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3249 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3250 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3251 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3254 extern cvar_t gl_picmip;
3255 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3258 unsigned char *pixels;
3259 unsigned char *bumppixels;
3260 unsigned char *basepixels = NULL;
3261 int basepixels_width = 0;
3262 int basepixels_height = 0;
3263 skinframe_t *skinframe;
3264 rtexture_t *ddsbase = NULL;
3265 qboolean ddshasalpha = false;
3266 float ddsavgcolor[4];
3267 char basename[MAX_QPATH];
3268 int miplevel = R_PicmipForFlags(textureflags);
3269 int savemiplevel = miplevel;
3272 if (cls.state == ca_dedicated)
3275 // return an existing skinframe if already loaded
3276 // if loading of the first image fails, don't make a new skinframe as it
3277 // would cause all future lookups of this to be missing
3278 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3279 if (skinframe && skinframe->base)
3282 Image_StripImageExtension(name, basename, sizeof(basename));
3284 // check for DDS texture file first
3285 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3287 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3288 if (basepixels == NULL)
3292 // FIXME handle miplevel
3294 if (developer_loading.integer)
3295 Con_Printf("loading skin \"%s\"\n", name);
3297 // we've got some pixels to store, so really allocate this new texture now
3299 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3300 skinframe->stain = NULL;
3301 skinframe->merged = NULL;
3302 skinframe->base = NULL;
3303 skinframe->pants = NULL;
3304 skinframe->shirt = NULL;
3305 skinframe->nmap = NULL;
3306 skinframe->gloss = NULL;
3307 skinframe->glow = NULL;
3308 skinframe->fog = NULL;
3309 skinframe->reflect = NULL;
3310 skinframe->hasalpha = false;
3314 skinframe->base = ddsbase;
3315 skinframe->hasalpha = ddshasalpha;
3316 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3317 if (r_loadfog && skinframe->hasalpha)
3318 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3319 //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]);
3323 basepixels_width = image_width;
3324 basepixels_height = image_height;
3325 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);
3326 if (textureflags & TEXF_ALPHA)
3328 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3330 if (basepixels[j] < 255)
3332 skinframe->hasalpha = true;
3336 if (r_loadfog && skinframe->hasalpha)
3338 // has transparent pixels
3339 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3340 for (j = 0;j < image_width * image_height * 4;j += 4)
3345 pixels[j+3] = basepixels[j+3];
3347 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);
3351 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3353 //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]);
3354 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3355 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3356 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3357 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3363 mymiplevel = savemiplevel;
3364 if (r_loadnormalmap)
3365 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);
3366 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3368 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3369 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3370 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3371 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3374 // _norm is the name used by tenebrae and has been adopted as standard
3375 if (r_loadnormalmap && skinframe->nmap == NULL)
3377 mymiplevel = savemiplevel;
3378 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3380 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);
3384 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3386 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3387 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3388 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);
3390 Mem_Free(bumppixels);
3392 else if (r_shadow_bumpscale_basetexture.value > 0)
3394 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3395 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3396 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);
3400 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3401 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3405 // _luma is supported only for tenebrae compatibility
3406 // _glow is the preferred name
3407 mymiplevel = savemiplevel;
3408 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))))
3410 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);
3412 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3413 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3415 Mem_Free(pixels);pixels = NULL;
3418 mymiplevel = savemiplevel;
3419 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3421 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3423 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3424 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3430 mymiplevel = savemiplevel;
3431 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3433 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);
3435 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3436 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3442 mymiplevel = savemiplevel;
3443 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3445 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);
3447 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3448 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3454 mymiplevel = savemiplevel;
3455 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3457 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);
3459 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3460 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3467 Mem_Free(basepixels);
3472 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3473 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3476 unsigned char *temp1, *temp2;
3477 skinframe_t *skinframe;
3479 if (cls.state == ca_dedicated)
3482 // if already loaded just return it, otherwise make a new skinframe
3483 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3484 if (skinframe && skinframe->base)
3487 skinframe->stain = NULL;
3488 skinframe->merged = NULL;
3489 skinframe->base = NULL;
3490 skinframe->pants = NULL;
3491 skinframe->shirt = NULL;
3492 skinframe->nmap = NULL;
3493 skinframe->gloss = NULL;
3494 skinframe->glow = NULL;
3495 skinframe->fog = NULL;
3496 skinframe->reflect = NULL;
3497 skinframe->hasalpha = false;
3499 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3503 if (developer_loading.integer)
3504 Con_Printf("loading 32bit skin \"%s\"\n", name);
3506 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3508 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3509 temp2 = temp1 + width * height * 4;
3510 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3511 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);
3514 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3515 if (textureflags & TEXF_ALPHA)
3517 for (i = 3;i < width * height * 4;i += 4)
3519 if (skindata[i] < 255)
3521 skinframe->hasalpha = true;
3525 if (r_loadfog && skinframe->hasalpha)
3527 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3528 memcpy(fogpixels, skindata, width * height * 4);
3529 for (i = 0;i < width * height * 4;i += 4)
3530 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3531 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3532 Mem_Free(fogpixels);
3536 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3537 //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]);
3542 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3546 skinframe_t *skinframe;
3548 if (cls.state == ca_dedicated)
3551 // if already loaded just return it, otherwise make a new skinframe
3552 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3553 if (skinframe && skinframe->base)
3556 skinframe->stain = NULL;
3557 skinframe->merged = NULL;
3558 skinframe->base = NULL;
3559 skinframe->pants = NULL;
3560 skinframe->shirt = NULL;
3561 skinframe->nmap = NULL;
3562 skinframe->gloss = NULL;
3563 skinframe->glow = NULL;
3564 skinframe->fog = NULL;
3565 skinframe->reflect = NULL;
3566 skinframe->hasalpha = false;
3568 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3572 if (developer_loading.integer)
3573 Con_Printf("loading quake skin \"%s\"\n", name);
3575 // 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)
3576 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3577 memcpy(skinframe->qpixels, skindata, width*height);
3578 skinframe->qwidth = width;
3579 skinframe->qheight = height;
3582 for (i = 0;i < width * height;i++)
3583 featuresmask |= palette_featureflags[skindata[i]];
3585 skinframe->hasalpha = false;
3586 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3587 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3588 skinframe->qgeneratemerged = true;
3589 skinframe->qgeneratebase = skinframe->qhascolormapping;
3590 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3592 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3593 //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]);
3598 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3602 unsigned char *skindata;
3604 if (!skinframe->qpixels)
3607 if (!skinframe->qhascolormapping)
3608 colormapped = false;
3612 if (!skinframe->qgeneratebase)
3617 if (!skinframe->qgeneratemerged)
3621 width = skinframe->qwidth;
3622 height = skinframe->qheight;
3623 skindata = skinframe->qpixels;
3625 if (skinframe->qgeneratenmap)
3627 unsigned char *temp1, *temp2;
3628 skinframe->qgeneratenmap = false;
3629 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3630 temp2 = temp1 + width * height * 4;
3631 // use either a custom palette or the quake palette
3632 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3633 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3634 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);
3638 if (skinframe->qgenerateglow)
3640 skinframe->qgenerateglow = false;
3641 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
3646 skinframe->qgeneratebase = false;
3647 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);
3648 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);
3649 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);
3653 skinframe->qgeneratemerged = false;
3654 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);
3657 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3659 Mem_Free(skinframe->qpixels);
3660 skinframe->qpixels = NULL;
3664 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)
3667 skinframe_t *skinframe;
3669 if (cls.state == ca_dedicated)
3672 // if already loaded just return it, otherwise make a new skinframe
3673 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3674 if (skinframe && skinframe->base)
3677 skinframe->stain = NULL;
3678 skinframe->merged = NULL;
3679 skinframe->base = NULL;
3680 skinframe->pants = NULL;
3681 skinframe->shirt = NULL;
3682 skinframe->nmap = NULL;
3683 skinframe->gloss = NULL;
3684 skinframe->glow = NULL;
3685 skinframe->fog = NULL;
3686 skinframe->reflect = NULL;
3687 skinframe->hasalpha = false;
3689 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3693 if (developer_loading.integer)
3694 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3696 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3697 if (textureflags & TEXF_ALPHA)
3699 for (i = 0;i < width * height;i++)
3701 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3703 skinframe->hasalpha = true;
3707 if (r_loadfog && skinframe->hasalpha)
3708 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3711 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3712 //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]);
3717 skinframe_t *R_SkinFrame_LoadMissing(void)
3719 skinframe_t *skinframe;
3721 if (cls.state == ca_dedicated)
3724 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3725 skinframe->stain = NULL;
3726 skinframe->merged = NULL;
3727 skinframe->base = NULL;
3728 skinframe->pants = NULL;
3729 skinframe->shirt = NULL;
3730 skinframe->nmap = NULL;
3731 skinframe->gloss = NULL;
3732 skinframe->glow = NULL;
3733 skinframe->fog = NULL;
3734 skinframe->reflect = NULL;
3735 skinframe->hasalpha = false;
3737 skinframe->avgcolor[0] = rand() / RAND_MAX;
3738 skinframe->avgcolor[1] = rand() / RAND_MAX;
3739 skinframe->avgcolor[2] = rand() / RAND_MAX;
3740 skinframe->avgcolor[3] = 1;
3745 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3746 typedef struct suffixinfo_s
3749 qboolean flipx, flipy, flipdiagonal;
3752 static suffixinfo_t suffix[3][6] =
3755 {"px", false, false, false},
3756 {"nx", false, false, false},
3757 {"py", false, false, false},
3758 {"ny", false, false, false},
3759 {"pz", false, false, false},
3760 {"nz", false, false, false}
3763 {"posx", false, false, false},
3764 {"negx", false, false, false},
3765 {"posy", false, false, false},
3766 {"negy", false, false, false},
3767 {"posz", false, false, false},
3768 {"negz", false, false, false}
3771 {"rt", true, false, true},
3772 {"lf", false, true, true},
3773 {"ft", true, true, false},
3774 {"bk", false, false, false},
3775 {"up", true, false, true},
3776 {"dn", true, false, true}
3780 static int componentorder[4] = {0, 1, 2, 3};
3782 rtexture_t *R_LoadCubemap(const char *basename)
3784 int i, j, cubemapsize;
3785 unsigned char *cubemappixels, *image_buffer;
3786 rtexture_t *cubemaptexture;
3788 // must start 0 so the first loadimagepixels has no requested width/height
3790 cubemappixels = NULL;
3791 cubemaptexture = NULL;
3792 // keep trying different suffix groups (posx, px, rt) until one loads
3793 for (j = 0;j < 3 && !cubemappixels;j++)
3795 // load the 6 images in the suffix group
3796 for (i = 0;i < 6;i++)
3798 // generate an image name based on the base and and suffix
3799 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3801 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3803 // an image loaded, make sure width and height are equal
3804 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3806 // if this is the first image to load successfully, allocate the cubemap memory
3807 if (!cubemappixels && image_width >= 1)
3809 cubemapsize = image_width;
3810 // note this clears to black, so unavailable sides are black
3811 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3813 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3815 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);
3818 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3820 Mem_Free(image_buffer);
3824 // if a cubemap loaded, upload it
3827 if (developer_loading.integer)
3828 Con_Printf("loading cubemap \"%s\"\n", basename);
3830 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);
3831 Mem_Free(cubemappixels);
3835 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3836 if (developer_loading.integer)
3838 Con_Printf("(tried tried images ");
3839 for (j = 0;j < 3;j++)
3840 for (i = 0;i < 6;i++)
3841 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3842 Con_Print(" and was unable to find any of them).\n");
3845 return cubemaptexture;
3848 rtexture_t *R_GetCubemap(const char *basename)
3851 for (i = 0;i < r_texture_numcubemaps;i++)
3852 if (r_texture_cubemaps[i] != NULL)
3853 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3854 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3855 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3856 return r_texture_whitecube;
3857 r_texture_numcubemaps++;
3858 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3859 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3860 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3861 return r_texture_cubemaps[i]->texture;
3864 void R_FreeCubemap(const char *basename)
3868 for (i = 0;i < r_texture_numcubemaps;i++)
3870 if (r_texture_cubemaps[i] != NULL)
3872 if (r_texture_cubemaps[i]->texture)
3874 if (developer_loading.integer)
3875 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3876 R_FreeTexture(r_texture_cubemaps[i]->texture);
3877 Mem_Free(r_texture_cubemaps[i]);
3878 r_texture_cubemaps[i] = NULL;
3884 void R_FreeCubemaps(void)
3887 for (i = 0;i < r_texture_numcubemaps;i++)
3889 if (developer_loading.integer)
3890 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3891 if (r_texture_cubemaps[i] != NULL)
3893 if (r_texture_cubemaps[i]->texture)
3894 R_FreeTexture(r_texture_cubemaps[i]->texture);
3895 Mem_Free(r_texture_cubemaps[i]);
3898 r_texture_numcubemaps = 0;
3901 void R_Main_FreeViewCache(void)
3903 if (r_refdef.viewcache.entityvisible)
3904 Mem_Free(r_refdef.viewcache.entityvisible);
3905 if (r_refdef.viewcache.world_pvsbits)
3906 Mem_Free(r_refdef.viewcache.world_pvsbits);
3907 if (r_refdef.viewcache.world_leafvisible)
3908 Mem_Free(r_refdef.viewcache.world_leafvisible);
3909 if (r_refdef.viewcache.world_surfacevisible)
3910 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3911 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3914 void R_Main_ResizeViewCache(void)
3916 int numentities = r_refdef.scene.numentities;
3917 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3918 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3919 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3920 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3921 if (r_refdef.viewcache.maxentities < numentities)
3923 r_refdef.viewcache.maxentities = numentities;
3924 if (r_refdef.viewcache.entityvisible)
3925 Mem_Free(r_refdef.viewcache.entityvisible);
3926 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3928 if (r_refdef.viewcache.world_numclusters != numclusters)
3930 r_refdef.viewcache.world_numclusters = numclusters;
3931 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3932 if (r_refdef.viewcache.world_pvsbits)
3933 Mem_Free(r_refdef.viewcache.world_pvsbits);
3934 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3936 if (r_refdef.viewcache.world_numleafs != numleafs)
3938 r_refdef.viewcache.world_numleafs = numleafs;
3939 if (r_refdef.viewcache.world_leafvisible)
3940 Mem_Free(r_refdef.viewcache.world_leafvisible);
3941 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3943 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3945 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3946 if (r_refdef.viewcache.world_surfacevisible)
3947 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3948 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3952 extern rtexture_t *loadingscreentexture;
3953 void gl_main_start(void)
3955 loadingscreentexture = NULL;
3956 r_texture_blanknormalmap = NULL;
3957 r_texture_white = NULL;
3958 r_texture_grey128 = NULL;
3959 r_texture_black = NULL;
3960 r_texture_whitecube = NULL;
3961 r_texture_normalizationcube = NULL;
3962 r_texture_fogattenuation = NULL;
3963 r_texture_fogheighttexture = NULL;
3964 r_texture_gammaramps = NULL;
3965 r_texture_numcubemaps = 0;
3967 r_loaddds = r_texture_dds_load.integer != 0;
3968 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3970 switch(vid.renderpath)
3972 case RENDERPATH_GL20:
3973 case RENDERPATH_D3D9:
3974 case RENDERPATH_D3D10:
3975 case RENDERPATH_D3D11:
3976 case RENDERPATH_SOFT:
3977 case RENDERPATH_GLES2:
3978 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3979 Cvar_SetValueQuick(&gl_combine, 1);
3980 Cvar_SetValueQuick(&r_glsl, 1);
3981 r_loadnormalmap = true;
3985 case RENDERPATH_GL13:
3986 case RENDERPATH_GLES1:
3987 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3988 Cvar_SetValueQuick(&gl_combine, 1);
3989 Cvar_SetValueQuick(&r_glsl, 0);
3990 r_loadnormalmap = false;
3991 r_loadgloss = false;
3994 case RENDERPATH_GL11:
3995 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3996 Cvar_SetValueQuick(&gl_combine, 0);
3997 Cvar_SetValueQuick(&r_glsl, 0);
3998 r_loadnormalmap = false;
3999 r_loadgloss = false;
4005 R_FrameData_Reset();
4009 memset(r_queries, 0, sizeof(r_queries));
4011 r_qwskincache = NULL;
4012 r_qwskincache_size = 0;
4014 // due to caching of texture_t references, the collision cache must be reset
4015 Collision_Cache_Reset(true);
4017 // set up r_skinframe loading system for textures
4018 memset(&r_skinframe, 0, sizeof(r_skinframe));
4019 r_skinframe.loadsequence = 1;
4020 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4022 r_main_texturepool = R_AllocTexturePool();
4023 R_BuildBlankTextures();
4025 if (vid.support.arb_texture_cube_map)
4028 R_BuildNormalizationCube();
4030 r_texture_fogattenuation = NULL;
4031 r_texture_fogheighttexture = NULL;
4032 r_texture_gammaramps = NULL;
4033 //r_texture_fogintensity = NULL;
4034 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4035 memset(&r_waterstate, 0, sizeof(r_waterstate));
4036 r_glsl_permutation = NULL;
4037 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4038 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4039 glslshaderstring = NULL;
4041 r_hlsl_permutation = NULL;
4042 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4043 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4045 hlslshaderstring = NULL;
4046 memset(&r_svbsp, 0, sizeof (r_svbsp));
4048 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4049 r_texture_numcubemaps = 0;
4051 r_refdef.fogmasktable_density = 0;
4054 void gl_main_shutdown(void)
4057 R_FrameData_Reset();
4059 R_Main_FreeViewCache();
4061 switch(vid.renderpath)
4063 case RENDERPATH_GL11:
4064 case RENDERPATH_GL13:
4065 case RENDERPATH_GL20:
4066 case RENDERPATH_GLES1:
4067 case RENDERPATH_GLES2:
4068 #ifdef GL_SAMPLES_PASSED_ARB
4070 qglDeleteQueriesARB(r_maxqueries, r_queries);
4073 case RENDERPATH_D3D9:
4074 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4076 case RENDERPATH_D3D10:
4077 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4079 case RENDERPATH_D3D11:
4080 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4082 case RENDERPATH_SOFT:
4088 memset(r_queries, 0, sizeof(r_queries));
4090 r_qwskincache = NULL;
4091 r_qwskincache_size = 0;
4093 // clear out the r_skinframe state
4094 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4095 memset(&r_skinframe, 0, sizeof(r_skinframe));
4098 Mem_Free(r_svbsp.nodes);
4099 memset(&r_svbsp, 0, sizeof (r_svbsp));
4100 R_FreeTexturePool(&r_main_texturepool);
4101 loadingscreentexture = NULL;
4102 r_texture_blanknormalmap = NULL;
4103 r_texture_white = NULL;
4104 r_texture_grey128 = NULL;
4105 r_texture_black = NULL;
4106 r_texture_whitecube = NULL;
4107 r_texture_normalizationcube = NULL;
4108 r_texture_fogattenuation = NULL;
4109 r_texture_fogheighttexture = NULL;
4110 r_texture_gammaramps = NULL;
4111 r_texture_numcubemaps = 0;
4112 //r_texture_fogintensity = NULL;
4113 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4114 memset(&r_waterstate, 0, sizeof(r_waterstate));
4117 r_glsl_permutation = NULL;
4118 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4119 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4120 glslshaderstring = NULL;
4122 r_hlsl_permutation = NULL;
4123 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4124 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4126 hlslshaderstring = NULL;
4129 extern void CL_ParseEntityLump(char *entitystring);
4130 void gl_main_newmap(void)
4132 // FIXME: move this code to client
4133 char *entities, entname[MAX_QPATH];
4135 Mem_Free(r_qwskincache);
4136 r_qwskincache = NULL;
4137 r_qwskincache_size = 0;
4140 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4141 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4143 CL_ParseEntityLump(entities);
4147 if (cl.worldmodel->brush.entities)
4148 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4150 R_Main_FreeViewCache();
4152 R_FrameData_Reset();
4155 void GL_Main_Init(void)
4157 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4159 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4160 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4161 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4162 if (gamemode == GAME_NEHAHRA)
4164 Cvar_RegisterVariable (&gl_fogenable);
4165 Cvar_RegisterVariable (&gl_fogdensity);
4166 Cvar_RegisterVariable (&gl_fogred);
4167 Cvar_RegisterVariable (&gl_foggreen);
4168 Cvar_RegisterVariable (&gl_fogblue);
4169 Cvar_RegisterVariable (&gl_fogstart);
4170 Cvar_RegisterVariable (&gl_fogend);
4171 Cvar_RegisterVariable (&gl_skyclip);
4173 Cvar_RegisterVariable(&r_motionblur);
4174 Cvar_RegisterVariable(&r_damageblur);
4175 Cvar_RegisterVariable(&r_motionblur_averaging);
4176 Cvar_RegisterVariable(&r_motionblur_randomize);
4177 Cvar_RegisterVariable(&r_motionblur_minblur);
4178 Cvar_RegisterVariable(&r_motionblur_maxblur);
4179 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4180 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4181 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4182 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4183 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4184 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4185 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4186 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4187 Cvar_RegisterVariable(&r_equalize_entities_by);
4188 Cvar_RegisterVariable(&r_equalize_entities_to);
4189 Cvar_RegisterVariable(&r_depthfirst);
4190 Cvar_RegisterVariable(&r_useinfinitefarclip);
4191 Cvar_RegisterVariable(&r_farclip_base);
4192 Cvar_RegisterVariable(&r_farclip_world);
4193 Cvar_RegisterVariable(&r_nearclip);
4194 Cvar_RegisterVariable(&r_deformvertexes);
4195 Cvar_RegisterVariable(&r_transparent);
4196 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4197 Cvar_RegisterVariable(&r_showoverdraw);
4198 Cvar_RegisterVariable(&r_showbboxes);
4199 Cvar_RegisterVariable(&r_showsurfaces);
4200 Cvar_RegisterVariable(&r_showtris);
4201 Cvar_RegisterVariable(&r_shownormals);
4202 Cvar_RegisterVariable(&r_showlighting);
4203 Cvar_RegisterVariable(&r_showshadowvolumes);
4204 Cvar_RegisterVariable(&r_showcollisionbrushes);
4205 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4206 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4207 Cvar_RegisterVariable(&r_showdisabledepthtest);
4208 Cvar_RegisterVariable(&r_drawportals);
4209 Cvar_RegisterVariable(&r_drawentities);
4210 Cvar_RegisterVariable(&r_draw2d);
4211 Cvar_RegisterVariable(&r_drawworld);
4212 Cvar_RegisterVariable(&r_cullentities_trace);
4213 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4214 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4215 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4216 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4217 Cvar_RegisterVariable(&r_sortentities);
4218 Cvar_RegisterVariable(&r_drawviewmodel);
4219 Cvar_RegisterVariable(&r_drawexteriormodel);
4220 Cvar_RegisterVariable(&r_speeds);
4221 Cvar_RegisterVariable(&r_fullbrights);
4222 Cvar_RegisterVariable(&r_wateralpha);
4223 Cvar_RegisterVariable(&r_dynamic);
4224 Cvar_RegisterVariable(&r_fakelight);
4225 Cvar_RegisterVariable(&r_fakelight_intensity);
4226 Cvar_RegisterVariable(&r_fullbright);
4227 Cvar_RegisterVariable(&r_shadows);
4228 Cvar_RegisterVariable(&r_shadows_darken);
4229 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4230 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4231 Cvar_RegisterVariable(&r_shadows_throwdistance);
4232 Cvar_RegisterVariable(&r_shadows_throwdirection);
4233 Cvar_RegisterVariable(&r_shadows_focus);
4234 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4235 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4236 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4237 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4238 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4239 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4240 Cvar_RegisterVariable(&r_fog_exp2);
4241 Cvar_RegisterVariable(&r_fog_clear);
4242 Cvar_RegisterVariable(&r_drawfog);
4243 Cvar_RegisterVariable(&r_transparentdepthmasking);
4244 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4245 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4246 Cvar_RegisterVariable(&r_texture_dds_load);
4247 Cvar_RegisterVariable(&r_texture_dds_save);
4248 Cvar_RegisterVariable(&r_textureunits);
4249 Cvar_RegisterVariable(&gl_combine);
4250 Cvar_RegisterVariable(&r_viewfbo);
4251 Cvar_RegisterVariable(&r_viewscale);
4252 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4253 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4254 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4255 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4256 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4257 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4258 Cvar_RegisterVariable(&r_glsl);
4259 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4260 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4261 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4262 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4263 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4264 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4265 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4266 Cvar_RegisterVariable(&r_glsl_postprocess);
4267 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4268 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4269 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4270 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4271 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4272 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4273 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4274 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4276 Cvar_RegisterVariable(&r_water);
4277 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4278 Cvar_RegisterVariable(&r_water_clippingplanebias);
4279 Cvar_RegisterVariable(&r_water_refractdistort);
4280 Cvar_RegisterVariable(&r_water_reflectdistort);
4281 Cvar_RegisterVariable(&r_water_scissormode);
4282 Cvar_RegisterVariable(&r_water_lowquality);
4284 Cvar_RegisterVariable(&r_lerpsprites);
4285 Cvar_RegisterVariable(&r_lerpmodels);
4286 Cvar_RegisterVariable(&r_lerplightstyles);
4287 Cvar_RegisterVariable(&r_waterscroll);
4288 Cvar_RegisterVariable(&r_bloom);
4289 Cvar_RegisterVariable(&r_bloom_colorscale);
4290 Cvar_RegisterVariable(&r_bloom_brighten);
4291 Cvar_RegisterVariable(&r_bloom_blur);
4292 Cvar_RegisterVariable(&r_bloom_resolution);
4293 Cvar_RegisterVariable(&r_bloom_colorexponent);
4294 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4295 Cvar_RegisterVariable(&r_hdr);
4296 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4297 Cvar_RegisterVariable(&r_hdr_glowintensity);
4298 Cvar_RegisterVariable(&r_hdr_range);
4299 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4300 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4301 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4302 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4303 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4304 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4305 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4306 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4307 Cvar_RegisterVariable(&developer_texturelogging);
4308 Cvar_RegisterVariable(&gl_lightmaps);
4309 Cvar_RegisterVariable(&r_test);
4310 Cvar_RegisterVariable(&r_glsl_saturation);
4311 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4312 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4313 Cvar_RegisterVariable(&r_framedatasize);
4314 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4315 Cvar_SetValue("r_fullbrights", 0);
4316 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4319 extern void R_Textures_Init(void);
4320 extern void GL_Draw_Init(void);
4321 extern void GL_Main_Init(void);
4322 extern void R_Shadow_Init(void);
4323 extern void R_Sky_Init(void);
4324 extern void GL_Surf_Init(void);
4325 extern void R_Particles_Init(void);
4326 extern void R_Explosion_Init(void);
4327 extern void gl_backend_init(void);
4328 extern void Sbar_Init(void);
4329 extern void R_LightningBeams_Init(void);
4330 extern void Mod_RenderInit(void);
4331 extern void Font_Init(void);
4333 void Render_Init(void)
4346 R_LightningBeams_Init();
4356 extern char *ENGINE_EXTENSIONS;
4359 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4360 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4361 gl_version = (const char *)qglGetString(GL_VERSION);
4362 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4366 if (!gl_platformextensions)
4367 gl_platformextensions = "";
4369 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4370 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4371 Con_Printf("GL_VERSION: %s\n", gl_version);
4372 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4373 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4375 VID_CheckExtensions();
4377 // LordHavoc: report supported extensions
4378 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4380 // clear to black (loading plaque will be seen over this)
4381 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4385 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4389 if (r_trippy.integer)
4391 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4393 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4396 p = r_refdef.view.frustum + i;
4401 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4405 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4409 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4413 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4417 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4421 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4425 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4429 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4437 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4441 if (r_trippy.integer)
4443 for (i = 0;i < numplanes;i++)
4450 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4454 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4458 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4462 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4466 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4470 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4474 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4478 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4486 //==================================================================================
4488 // LordHavoc: this stores temporary data used within the same frame
4490 typedef struct r_framedata_mem_s
4492 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4493 size_t size; // how much usable space
4494 size_t current; // how much space in use
4495 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4496 size_t wantedsize; // how much space was allocated
4497 unsigned char *data; // start of real data (16byte aligned)
4501 static r_framedata_mem_t *r_framedata_mem;
4503 void R_FrameData_Reset(void)
4505 while (r_framedata_mem)
4507 r_framedata_mem_t *next = r_framedata_mem->purge;
4508 Mem_Free(r_framedata_mem);
4509 r_framedata_mem = next;
4513 void R_FrameData_Resize(void)
4516 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4517 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4518 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4520 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4521 newmem->wantedsize = wantedsize;
4522 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4523 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4524 newmem->current = 0;
4526 newmem->purge = r_framedata_mem;
4527 r_framedata_mem = newmem;
4531 void R_FrameData_NewFrame(void)
4533 R_FrameData_Resize();
4534 if (!r_framedata_mem)
4536 // if we ran out of space on the last frame, free the old memory now
4537 while (r_framedata_mem->purge)
4539 // repeatedly remove the second item in the list, leaving only head
4540 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4541 Mem_Free(r_framedata_mem->purge);
4542 r_framedata_mem->purge = next;
4544 // reset the current mem pointer
4545 r_framedata_mem->current = 0;
4546 r_framedata_mem->mark = 0;
4549 void *R_FrameData_Alloc(size_t size)
4553 // align to 16 byte boundary - the data pointer is already aligned, so we
4554 // only need to ensure the size of every allocation is also aligned
4555 size = (size + 15) & ~15;
4557 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4559 // emergency - we ran out of space, allocate more memory
4560 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4561 R_FrameData_Resize();
4564 data = r_framedata_mem->data + r_framedata_mem->current;
4565 r_framedata_mem->current += size;
4567 // count the usage for stats
4568 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4569 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4571 return (void *)data;
4574 void *R_FrameData_Store(size_t size, void *data)
4576 void *d = R_FrameData_Alloc(size);
4578 memcpy(d, data, size);
4582 void R_FrameData_SetMark(void)
4584 if (!r_framedata_mem)
4586 r_framedata_mem->mark = r_framedata_mem->current;
4589 void R_FrameData_ReturnToMark(void)
4591 if (!r_framedata_mem)
4593 r_framedata_mem->current = r_framedata_mem->mark;
4596 //==================================================================================
4598 // LordHavoc: animcache originally written by Echon, rewritten since then
4601 * Animation cache prevents re-generating mesh data for an animated model
4602 * multiple times in one frame for lighting, shadowing, reflections, etc.
4605 void R_AnimCache_Free(void)
4609 void R_AnimCache_ClearCache(void)
4612 entity_render_t *ent;
4614 for (i = 0;i < r_refdef.scene.numentities;i++)
4616 ent = r_refdef.scene.entities[i];
4617 ent->animcache_vertex3f = NULL;
4618 ent->animcache_normal3f = NULL;
4619 ent->animcache_svector3f = NULL;
4620 ent->animcache_tvector3f = NULL;
4621 ent->animcache_vertexmesh = NULL;
4622 ent->animcache_vertex3fbuffer = NULL;
4623 ent->animcache_vertexmeshbuffer = NULL;
4627 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4631 // check if we need the meshbuffers
4632 if (!vid.useinterleavedarrays)
4635 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4636 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4637 // TODO: upload vertex3f buffer?
4638 if (ent->animcache_vertexmesh)
4640 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4641 for (i = 0;i < numvertices;i++)
4642 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4643 if (ent->animcache_svector3f)
4644 for (i = 0;i < numvertices;i++)
4645 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4646 if (ent->animcache_tvector3f)
4647 for (i = 0;i < numvertices;i++)
4648 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4649 if (ent->animcache_normal3f)
4650 for (i = 0;i < numvertices;i++)
4651 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4652 // TODO: upload vertexmeshbuffer?
4656 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4658 dp_model_t *model = ent->model;
4660 // see if it's already cached this frame
4661 if (ent->animcache_vertex3f)
4663 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4664 if (wantnormals || wanttangents)
4666 if (ent->animcache_normal3f)
4667 wantnormals = false;
4668 if (ent->animcache_svector3f)
4669 wanttangents = false;
4670 if (wantnormals || wanttangents)
4672 numvertices = model->surfmesh.num_vertices;
4674 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4677 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4678 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4680 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4681 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4687 // see if this ent is worth caching
4688 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4690 // get some memory for this entity and generate mesh data
4691 numvertices = model->surfmesh.num_vertices;
4692 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4694 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4697 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4698 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4700 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4701 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4706 void R_AnimCache_CacheVisibleEntities(void)
4709 qboolean wantnormals = true;
4710 qboolean wanttangents = !r_showsurfaces.integer;
4712 switch(vid.renderpath)
4714 case RENDERPATH_GL20:
4715 case RENDERPATH_D3D9:
4716 case RENDERPATH_D3D10:
4717 case RENDERPATH_D3D11:
4718 case RENDERPATH_GLES2:
4720 case RENDERPATH_GL11:
4721 case RENDERPATH_GL13:
4722 case RENDERPATH_GLES1:
4723 wanttangents = false;
4725 case RENDERPATH_SOFT:
4729 if (r_shownormals.integer)
4730 wanttangents = wantnormals = true;
4732 // TODO: thread this
4733 // NOTE: R_PrepareRTLights() also caches entities
4735 for (i = 0;i < r_refdef.scene.numentities;i++)
4736 if (r_refdef.viewcache.entityvisible[i])
4737 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4740 //==================================================================================
4742 extern cvar_t r_overheadsprites_pushback;
4744 static void R_View_UpdateEntityLighting (void)
4747 entity_render_t *ent;
4748 vec3_t tempdiffusenormal, avg;
4749 vec_t f, fa, fd, fdd;
4750 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4752 for (i = 0;i < r_refdef.scene.numentities;i++)
4754 ent = r_refdef.scene.entities[i];
4756 // skip unseen models
4757 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4761 if (ent->model && ent->model->brush.num_leafs)
4763 // TODO: use modellight for r_ambient settings on world?
4764 VectorSet(ent->modellight_ambient, 0, 0, 0);
4765 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4766 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4770 // fetch the lighting from the worldmodel data
4771 VectorClear(ent->modellight_ambient);
4772 VectorClear(ent->modellight_diffuse);
4773 VectorClear(tempdiffusenormal);
4774 if (ent->flags & RENDER_LIGHT)
4777 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4779 // complete lightning for lit sprites
4780 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4781 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4783 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4784 org[2] = org[2] + r_overheadsprites_pushback.value;
4785 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4788 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4790 if(ent->flags & RENDER_EQUALIZE)
4792 // first fix up ambient lighting...
4793 if(r_equalize_entities_minambient.value > 0)
4795 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4798 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4799 if(fa < r_equalize_entities_minambient.value * fd)
4802 // fa'/fd' = minambient
4803 // fa'+0.25*fd' = fa+0.25*fd
4805 // fa' = fd' * minambient
4806 // fd'*(0.25+minambient) = fa+0.25*fd
4808 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4809 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4811 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4812 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
4813 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4814 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4819 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4821 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4822 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4826 // adjust brightness and saturation to target
4827 avg[0] = avg[1] = avg[2] = fa / f;
4828 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4829 avg[0] = avg[1] = avg[2] = fd / f;
4830 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4836 VectorSet(ent->modellight_ambient, 1, 1, 1);
4838 // move the light direction into modelspace coordinates for lighting code
4839 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4840 if(VectorLength2(ent->modellight_lightdir) == 0)
4841 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4842 VectorNormalize(ent->modellight_lightdir);
4846 #define MAX_LINEOFSIGHTTRACES 64
4848 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4851 vec3_t boxmins, boxmaxs;
4854 dp_model_t *model = r_refdef.scene.worldmodel;
4856 if (!model || !model->brush.TraceLineOfSight)
4859 // expand the box a little
4860 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4861 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4862 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4863 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4864 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4865 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4867 // return true if eye is inside enlarged box
4868 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4872 VectorCopy(eye, start);
4873 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4874 if (model->brush.TraceLineOfSight(model, start, end))
4877 // try various random positions
4878 for (i = 0;i < numsamples;i++)
4880 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4881 if (model->brush.TraceLineOfSight(model, start, end))
4889 static void R_View_UpdateEntityVisible (void)
4894 entity_render_t *ent;
4896 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4897 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4898 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4899 : RENDER_EXTERIORMODEL;
4900 if (!r_drawviewmodel.integer)
4901 renderimask |= RENDER_VIEWMODEL;
4902 if (!r_drawexteriormodel.integer)
4903 renderimask |= RENDER_EXTERIORMODEL;
4904 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4906 // worldmodel can check visibility
4907 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4908 for (i = 0;i < r_refdef.scene.numentities;i++)
4910 ent = r_refdef.scene.entities[i];
4911 if (!(ent->flags & renderimask))
4912 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)))
4913 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))
4914 r_refdef.viewcache.entityvisible[i] = true;
4919 // no worldmodel or it can't check visibility
4920 for (i = 0;i < r_refdef.scene.numentities;i++)
4922 ent = r_refdef.scene.entities[i];
4923 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));
4926 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4927 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4929 for (i = 0;i < r_refdef.scene.numentities;i++)
4931 if (!r_refdef.viewcache.entityvisible[i])
4933 ent = r_refdef.scene.entities[i];
4934 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4936 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4938 continue; // temp entities do pvs only
4939 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4940 ent->last_trace_visibility = realtime;
4941 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4942 r_refdef.viewcache.entityvisible[i] = 0;
4948 /// only used if skyrendermasked, and normally returns false
4949 int R_DrawBrushModelsSky (void)
4952 entity_render_t *ent;
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->model || !ent->model->DrawSky)
4962 ent->model->DrawSky(ent);
4968 static void R_DrawNoModel(entity_render_t *ent);
4969 static void R_DrawModels(void)
4972 entity_render_t *ent;
4974 for (i = 0;i < r_refdef.scene.numentities;i++)
4976 if (!r_refdef.viewcache.entityvisible[i])
4978 ent = r_refdef.scene.entities[i];
4979 r_refdef.stats.entities++;
4981 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4984 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4985 Con_Printf("R_DrawModels\n");
4986 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]);
4987 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);
4988 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);
4991 if (ent->model && ent->model->Draw != NULL)
4992 ent->model->Draw(ent);
4998 static void R_DrawModelsDepth(void)
5001 entity_render_t *ent;
5003 for (i = 0;i < r_refdef.scene.numentities;i++)
5005 if (!r_refdef.viewcache.entityvisible[i])
5007 ent = r_refdef.scene.entities[i];
5008 if (ent->model && ent->model->DrawDepth != NULL)
5009 ent->model->DrawDepth(ent);
5013 static void R_DrawModelsDebug(void)
5016 entity_render_t *ent;
5018 for (i = 0;i < r_refdef.scene.numentities;i++)
5020 if (!r_refdef.viewcache.entityvisible[i])
5022 ent = r_refdef.scene.entities[i];
5023 if (ent->model && ent->model->DrawDebug != NULL)
5024 ent->model->DrawDebug(ent);
5028 static void R_DrawModelsAddWaterPlanes(void)
5031 entity_render_t *ent;
5033 for (i = 0;i < r_refdef.scene.numentities;i++)
5035 if (!r_refdef.viewcache.entityvisible[i])
5037 ent = r_refdef.scene.entities[i];
5038 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5039 ent->model->DrawAddWaterPlanes(ent);
5043 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5045 if (r_hdr_irisadaptation.integer)
5049 vec3_t diffusenormal;
5053 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5054 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5055 brightness = max(0.0000001f, brightness);
5056 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5057 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5058 current = r_hdr_irisadaptation_value.value;
5060 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5061 else if (current > goal)
5062 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5063 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5064 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5066 else if (r_hdr_irisadaptation_value.value != 1.0f)
5067 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5070 static void R_View_SetFrustum(const int *scissor)
5073 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5074 vec3_t forward, left, up, origin, v;
5078 // flipped x coordinates (because x points left here)
5079 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5080 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5082 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5083 switch(vid.renderpath)
5085 case RENDERPATH_D3D9:
5086 case RENDERPATH_D3D10:
5087 case RENDERPATH_D3D11:
5088 // non-flipped y coordinates
5089 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5090 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5092 case RENDERPATH_SOFT:
5093 case RENDERPATH_GL11:
5094 case RENDERPATH_GL13:
5095 case RENDERPATH_GL20:
5096 case RENDERPATH_GLES1:
5097 case RENDERPATH_GLES2:
5098 // non-flipped y coordinates
5099 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5100 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5105 // we can't trust r_refdef.view.forward and friends in reflected scenes
5106 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5109 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5110 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5111 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5112 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5113 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5114 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5115 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5116 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5117 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5118 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5119 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5120 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5124 zNear = r_refdef.nearclip;
5125 nudge = 1.0 - 1.0 / (1<<23);
5126 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5127 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5128 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5129 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5130 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5131 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5132 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5133 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5139 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5140 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5141 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5142 r_refdef.view.frustum[0].dist = m[15] - m[12];
5144 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5145 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5146 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5147 r_refdef.view.frustum[1].dist = m[15] + m[12];
5149 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5150 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5151 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5152 r_refdef.view.frustum[2].dist = m[15] - m[13];
5154 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5155 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5156 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5157 r_refdef.view.frustum[3].dist = m[15] + m[13];
5159 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5160 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5161 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5162 r_refdef.view.frustum[4].dist = m[15] - m[14];
5164 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5165 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5166 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5167 r_refdef.view.frustum[5].dist = m[15] + m[14];
5170 if (r_refdef.view.useperspective)
5172 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5173 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]);
5174 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]);
5175 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]);
5176 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]);
5178 // then the normals from the corners relative to origin
5179 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5180 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5181 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5182 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5184 // in a NORMAL view, forward cross left == up
5185 // in a REFLECTED view, forward cross left == down
5186 // so our cross products above need to be adjusted for a left handed coordinate system
5187 CrossProduct(forward, left, v);
5188 if(DotProduct(v, up) < 0)
5190 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5191 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5192 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5193 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5196 // Leaving those out was a mistake, those were in the old code, and they
5197 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5198 // I couldn't reproduce it after adding those normalizations. --blub
5199 VectorNormalize(r_refdef.view.frustum[0].normal);
5200 VectorNormalize(r_refdef.view.frustum[1].normal);
5201 VectorNormalize(r_refdef.view.frustum[2].normal);
5202 VectorNormalize(r_refdef.view.frustum[3].normal);
5204 // make the corners absolute
5205 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5206 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5207 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5208 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5211 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5213 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5214 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5215 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5216 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5217 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5221 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5222 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5223 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5224 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5225 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5226 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5227 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5228 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5229 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5230 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5232 r_refdef.view.numfrustumplanes = 5;
5234 if (r_refdef.view.useclipplane)
5236 r_refdef.view.numfrustumplanes = 6;
5237 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5240 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5241 PlaneClassify(r_refdef.view.frustum + i);
5243 // LordHavoc: note to all quake engine coders, Quake had a special case
5244 // for 90 degrees which assumed a square view (wrong), so I removed it,
5245 // Quake2 has it disabled as well.
5247 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5248 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5249 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5250 //PlaneClassify(&frustum[0]);
5252 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5253 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5254 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5255 //PlaneClassify(&frustum[1]);
5257 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5258 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5259 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5260 //PlaneClassify(&frustum[2]);
5262 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5263 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5264 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5265 //PlaneClassify(&frustum[3]);
5268 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5269 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5270 //PlaneClassify(&frustum[4]);
5273 void R_View_UpdateWithScissor(const int *myscissor)
5275 R_Main_ResizeViewCache();
5276 R_View_SetFrustum(myscissor);
5277 R_View_WorldVisibility(r_refdef.view.useclipplane);
5278 R_View_UpdateEntityVisible();
5279 R_View_UpdateEntityLighting();
5282 void R_View_Update(void)
5284 R_Main_ResizeViewCache();
5285 R_View_SetFrustum(NULL);
5286 R_View_WorldVisibility(r_refdef.view.useclipplane);
5287 R_View_UpdateEntityVisible();
5288 R_View_UpdateEntityLighting();
5291 float viewscalefpsadjusted = 1.0f;
5293 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5295 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5296 scale = bound(0.03125f, scale, 1.0f);
5297 *outwidth = (int)ceil(width * scale);
5298 *outheight = (int)ceil(height * scale);
5301 void R_Mesh_SetMainRenderTargets(void)
5303 if (r_bloomstate.fbo_framebuffer)
5304 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5306 R_Mesh_ResetRenderTargets();
5309 void R_SetupView(qboolean allowwaterclippingplane)
5311 const float *customclipplane = NULL;
5313 int scaledwidth, scaledheight;
5314 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5316 // LordHavoc: couldn't figure out how to make this approach the
5317 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5318 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5319 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5320 dist = r_refdef.view.clipplane.dist;
5321 plane[0] = r_refdef.view.clipplane.normal[0];
5322 plane[1] = r_refdef.view.clipplane.normal[1];
5323 plane[2] = r_refdef.view.clipplane.normal[2];
5325 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5328 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5329 if (!r_refdef.view.useperspective)
5330 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);
5331 else if (vid.stencil && r_useinfinitefarclip.integer)
5332 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);
5334 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);
5335 R_Mesh_SetMainRenderTargets();
5336 R_SetViewport(&r_refdef.view.viewport);
5337 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5339 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5340 float screenplane[4];
5341 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5342 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5343 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5344 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5345 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5349 void R_EntityMatrix(const matrix4x4_t *matrix)
5351 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5353 gl_modelmatrixchanged = false;
5354 gl_modelmatrix = *matrix;
5355 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5356 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5357 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5358 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5360 switch(vid.renderpath)
5362 case RENDERPATH_D3D9:
5364 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5365 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5368 case RENDERPATH_D3D10:
5369 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5371 case RENDERPATH_D3D11:
5372 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5374 case RENDERPATH_GL11:
5375 case RENDERPATH_GL13:
5376 case RENDERPATH_GLES1:
5377 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5379 case RENDERPATH_SOFT:
5380 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5381 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5383 case RENDERPATH_GL20:
5384 case RENDERPATH_GLES2:
5385 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5386 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5392 void R_ResetViewRendering2D(void)
5394 r_viewport_t viewport;
5397 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5398 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);
5399 R_Mesh_ResetRenderTargets();
5400 R_SetViewport(&viewport);
5401 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5402 GL_Color(1, 1, 1, 1);
5403 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5404 GL_BlendFunc(GL_ONE, GL_ZERO);
5405 GL_ScissorTest(false);
5406 GL_DepthMask(false);
5407 GL_DepthRange(0, 1);
5408 GL_DepthTest(false);
5409 GL_DepthFunc(GL_LEQUAL);
5410 R_EntityMatrix(&identitymatrix);
5411 R_Mesh_ResetTextureState();
5412 GL_PolygonOffset(0, 0);
5413 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5414 switch(vid.renderpath)
5416 case RENDERPATH_GL11:
5417 case RENDERPATH_GL13:
5418 case RENDERPATH_GL20:
5419 case RENDERPATH_GLES1:
5420 case RENDERPATH_GLES2:
5421 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5423 case RENDERPATH_D3D9:
5424 case RENDERPATH_D3D10:
5425 case RENDERPATH_D3D11:
5426 case RENDERPATH_SOFT:
5429 GL_CullFace(GL_NONE);
5432 void R_ResetViewRendering3D(void)
5437 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5438 GL_Color(1, 1, 1, 1);
5439 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5440 GL_BlendFunc(GL_ONE, GL_ZERO);
5441 GL_ScissorTest(true);
5443 GL_DepthRange(0, 1);
5445 GL_DepthFunc(GL_LEQUAL);
5446 R_EntityMatrix(&identitymatrix);
5447 R_Mesh_ResetTextureState();
5448 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5449 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5450 switch(vid.renderpath)
5452 case RENDERPATH_GL11:
5453 case RENDERPATH_GL13:
5454 case RENDERPATH_GL20:
5455 case RENDERPATH_GLES1:
5456 case RENDERPATH_GLES2:
5457 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5459 case RENDERPATH_D3D9:
5460 case RENDERPATH_D3D10:
5461 case RENDERPATH_D3D11:
5462 case RENDERPATH_SOFT:
5465 GL_CullFace(r_refdef.view.cullface_back);
5470 R_RenderView_UpdateViewVectors
5473 static void R_RenderView_UpdateViewVectors(void)
5475 // break apart the view matrix into vectors for various purposes
5476 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5477 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5478 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5479 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5480 // make an inverted copy of the view matrix for tracking sprites
5481 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5484 void R_RenderScene(void);
5485 void R_RenderWaterPlanes(void);
5487 static void R_Water_StartFrame(void)
5490 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5491 r_waterstate_waterplane_t *p;
5493 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5496 switch(vid.renderpath)
5498 case RENDERPATH_GL20:
5499 case RENDERPATH_D3D9:
5500 case RENDERPATH_D3D10:
5501 case RENDERPATH_D3D11:
5502 case RENDERPATH_SOFT:
5503 case RENDERPATH_GLES2:
5505 case RENDERPATH_GL11:
5506 case RENDERPATH_GL13:
5507 case RENDERPATH_GLES1:
5511 // set waterwidth and waterheight to the water resolution that will be
5512 // used (often less than the screen resolution for faster rendering)
5513 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5515 // calculate desired texture sizes
5516 // can't use water if the card does not support the texture size
5517 if (!r_water.integer || r_showsurfaces.integer)
5518 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5519 else if (vid.support.arb_texture_non_power_of_two)
5521 texturewidth = waterwidth;
5522 textureheight = waterheight;
5523 camerawidth = waterwidth;
5524 cameraheight = waterheight;
5528 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5529 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5530 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5531 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5534 // allocate textures as needed
5535 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5537 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5538 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5540 if (p->texture_refraction)
5541 R_FreeTexture(p->texture_refraction);
5542 p->texture_refraction = NULL;
5543 if (p->texture_reflection)
5544 R_FreeTexture(p->texture_reflection);
5545 p->texture_reflection = NULL;
5546 if (p->texture_camera)
5547 R_FreeTexture(p->texture_camera);
5548 p->texture_camera = NULL;
5550 memset(&r_waterstate, 0, sizeof(r_waterstate));
5551 r_waterstate.texturewidth = texturewidth;
5552 r_waterstate.textureheight = textureheight;
5553 r_waterstate.camerawidth = camerawidth;
5554 r_waterstate.cameraheight = cameraheight;
5557 if (r_waterstate.texturewidth)
5559 int scaledwidth, scaledheight;
5561 r_waterstate.enabled = true;
5563 // when doing a reduced render (HDR) we want to use a smaller area
5564 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5565 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5566 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5568 // set up variables that will be used in shader setup
5569 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5570 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5571 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5572 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5575 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5576 r_waterstate.numwaterplanes = 0;
5579 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5581 int triangleindex, planeindex;
5587 r_waterstate_waterplane_t *p;
5588 texture_t *t = R_GetCurrentTexture(surface->texture);
5590 // just use the first triangle with a valid normal for any decisions
5591 VectorClear(normal);
5592 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5594 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5595 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5596 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5597 TriangleNormal(vert[0], vert[1], vert[2], normal);
5598 if (VectorLength2(normal) >= 0.001)
5602 VectorCopy(normal, plane.normal);
5603 VectorNormalize(plane.normal);
5604 plane.dist = DotProduct(vert[0], plane.normal);
5605 PlaneClassify(&plane);
5606 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5608 // skip backfaces (except if nocullface is set)
5609 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5611 VectorNegate(plane.normal, plane.normal);
5613 PlaneClassify(&plane);
5617 // find a matching plane if there is one
5618 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5619 if(p->camera_entity == t->camera_entity)
5620 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5622 if (planeindex >= r_waterstate.maxwaterplanes)
5623 return; // nothing we can do, out of planes
5625 // if this triangle does not fit any known plane rendered this frame, add one
5626 if (planeindex >= r_waterstate.numwaterplanes)
5628 // store the new plane
5629 r_waterstate.numwaterplanes++;
5631 // clear materialflags and pvs
5632 p->materialflags = 0;
5633 p->pvsvalid = false;
5634 p->camera_entity = t->camera_entity;
5635 VectorCopy(surface->mins, p->mins);
5636 VectorCopy(surface->maxs, p->maxs);
5641 p->mins[0] = min(p->mins[0], surface->mins[0]);
5642 p->mins[1] = min(p->mins[1], surface->mins[1]);
5643 p->mins[2] = min(p->mins[2], surface->mins[2]);
5644 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5645 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5646 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5648 // merge this surface's materialflags into the waterplane
5649 p->materialflags |= t->currentmaterialflags;
5650 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5652 // merge this surface's PVS into the waterplane
5653 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5654 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5655 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5657 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5663 extern cvar_t r_drawparticles;
5664 extern cvar_t r_drawdecals;
5666 static void R_Water_ProcessPlanes(void)
5669 r_refdef_view_t originalview;
5670 r_refdef_view_t myview;
5671 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;
5672 r_waterstate_waterplane_t *p;
5675 originalview = r_refdef.view;
5677 // lowquality hack, temporarily shut down some cvars and restore afterwards
5678 qualityreduction = r_water_lowquality.integer;
5679 if (qualityreduction > 0)
5681 if (qualityreduction >= 1)
5683 old_r_shadows = r_shadows.integer;
5684 old_r_worldrtlight = r_shadow_realtime_world.integer;
5685 old_r_dlight = r_shadow_realtime_dlight.integer;
5686 Cvar_SetValueQuick(&r_shadows, 0);
5687 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5688 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5690 if (qualityreduction >= 2)
5692 old_r_dynamic = r_dynamic.integer;
5693 old_r_particles = r_drawparticles.integer;
5694 old_r_decals = r_drawdecals.integer;
5695 Cvar_SetValueQuick(&r_dynamic, 0);
5696 Cvar_SetValueQuick(&r_drawparticles, 0);
5697 Cvar_SetValueQuick(&r_drawdecals, 0);
5701 // make sure enough textures are allocated
5702 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5704 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5706 if (!p->texture_refraction)
5707 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);
5708 if (!p->texture_refraction)
5711 else if (p->materialflags & MATERIALFLAG_CAMERA)
5713 if (!p->texture_camera)
5714 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);
5715 if (!p->texture_camera)
5719 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5721 if (!p->texture_reflection)
5722 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);
5723 if (!p->texture_reflection)
5729 r_refdef.view = originalview;
5730 r_refdef.view.showdebug = false;
5731 r_refdef.view.width = r_waterstate.waterwidth;
5732 r_refdef.view.height = r_waterstate.waterheight;
5733 r_refdef.view.useclipplane = true;
5734 myview = r_refdef.view;
5735 r_waterstate.renderingscene = true;
5736 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5738 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5740 r_refdef.view = myview;
5741 if(r_water_scissormode.integer)
5744 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5745 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5748 // render reflected scene and copy into texture
5749 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5750 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5751 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5752 r_refdef.view.clipplane = p->plane;
5753 // reverse the cullface settings for this render
5754 r_refdef.view.cullface_front = GL_FRONT;
5755 r_refdef.view.cullface_back = GL_BACK;
5756 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5758 r_refdef.view.usecustompvs = true;
5760 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5762 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5765 R_ResetViewRendering3D();
5766 R_ClearScreen(r_refdef.fogenabled);
5767 if(r_water_scissormode.integer & 2)
5768 R_View_UpdateWithScissor(myscissor);
5771 if(r_water_scissormode.integer & 1)
5772 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5775 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);
5778 // render the normal view scene and copy into texture
5779 // (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)
5780 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5782 r_refdef.view = myview;
5783 if(r_water_scissormode.integer)
5786 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5787 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5790 r_waterstate.renderingrefraction = true;
5792 r_refdef.view.clipplane = p->plane;
5793 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5794 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5796 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5798 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5799 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5800 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5801 R_RenderView_UpdateViewVectors();
5802 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5804 r_refdef.view.usecustompvs = true;
5805 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);
5809 PlaneClassify(&r_refdef.view.clipplane);
5811 R_ResetViewRendering3D();
5812 R_ClearScreen(r_refdef.fogenabled);
5813 if(r_water_scissormode.integer & 2)
5814 R_View_UpdateWithScissor(myscissor);
5817 if(r_water_scissormode.integer & 1)
5818 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5821 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);
5822 r_waterstate.renderingrefraction = false;
5824 else if (p->materialflags & MATERIALFLAG_CAMERA)
5826 r_refdef.view = myview;
5828 r_refdef.view.clipplane = p->plane;
5829 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5830 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5832 r_refdef.view.width = r_waterstate.camerawidth;
5833 r_refdef.view.height = r_waterstate.cameraheight;
5834 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5835 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5837 if(p->camera_entity)
5839 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5840 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5843 // note: all of the view is used for displaying... so
5844 // there is no use in scissoring
5846 // reverse the cullface settings for this render
5847 r_refdef.view.cullface_front = GL_FRONT;
5848 r_refdef.view.cullface_back = GL_BACK;
5849 // also reverse the view matrix
5850 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
5851 R_RenderView_UpdateViewVectors();
5852 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5854 r_refdef.view.usecustompvs = true;
5855 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);
5858 // camera needs no clipplane
5859 r_refdef.view.useclipplane = false;
5861 PlaneClassify(&r_refdef.view.clipplane);
5863 R_ResetViewRendering3D();
5864 R_ClearScreen(r_refdef.fogenabled);
5868 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);
5869 r_waterstate.renderingrefraction = false;
5873 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5874 r_waterstate.renderingscene = false;
5875 r_refdef.view = originalview;
5876 R_ResetViewRendering3D();
5877 R_ClearScreen(r_refdef.fogenabled);
5881 r_refdef.view = originalview;
5882 r_waterstate.renderingscene = false;
5883 Cvar_SetValueQuick(&r_water, 0);
5884 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5886 // lowquality hack, restore cvars
5887 if (qualityreduction > 0)
5889 if (qualityreduction >= 1)
5891 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5892 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5893 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5895 if (qualityreduction >= 2)
5897 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5898 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5899 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5904 void R_Bloom_StartFrame(void)
5906 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5907 int viewwidth, viewheight;
5910 if (r_viewscale_fpsscaling.integer)
5912 double actualframetime;
5913 double targetframetime;
5915 actualframetime = r_refdef.lastdrawscreentime;
5916 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5917 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5918 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5919 if (r_viewscale_fpsscaling_stepsize.value > 0)
5920 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5921 viewscalefpsadjusted += adjust;
5922 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5925 viewscalefpsadjusted = 1.0f;
5927 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5929 switch(vid.renderpath)
5931 case RENDERPATH_GL20:
5932 case RENDERPATH_D3D9:
5933 case RENDERPATH_D3D10:
5934 case RENDERPATH_D3D11:
5935 case RENDERPATH_SOFT:
5936 case RENDERPATH_GLES2:
5938 case RENDERPATH_GL11:
5939 case RENDERPATH_GL13:
5940 case RENDERPATH_GLES1:
5944 // set bloomwidth and bloomheight to the bloom resolution that will be
5945 // used (often less than the screen resolution for faster rendering)
5946 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5947 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5948 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5949 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5950 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5952 // calculate desired texture sizes
5953 if (vid.support.arb_texture_non_power_of_two)
5955 screentexturewidth = vid.width;
5956 screentextureheight = vid.height;
5957 bloomtexturewidth = r_bloomstate.bloomwidth;
5958 bloomtextureheight = r_bloomstate.bloomheight;
5962 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5963 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5964 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5965 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5968 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))
5970 Cvar_SetValueQuick(&r_hdr, 0);
5971 Cvar_SetValueQuick(&r_bloom, 0);
5972 Cvar_SetValueQuick(&r_motionblur, 0);
5973 Cvar_SetValueQuick(&r_damageblur, 0);
5976 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)
5977 screentexturewidth = screentextureheight = 0;
5978 if (!r_hdr.integer && !r_bloom.integer)
5979 bloomtexturewidth = bloomtextureheight = 0;
5981 textype = TEXTYPE_COLORBUFFER;
5982 switch (vid.renderpath)
5984 case RENDERPATH_GL20:
5985 case RENDERPATH_GLES2:
5986 if (vid.support.ext_framebuffer_object)
5988 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5989 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5992 case RENDERPATH_GL11:
5993 case RENDERPATH_GL13:
5994 case RENDERPATH_GLES1:
5995 case RENDERPATH_D3D9:
5996 case RENDERPATH_D3D10:
5997 case RENDERPATH_D3D11:
5998 case RENDERPATH_SOFT:
6002 // allocate textures as needed
6003 if (r_bloomstate.screentexturewidth != screentexturewidth
6004 || r_bloomstate.screentextureheight != screentextureheight
6005 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6006 || r_bloomstate.bloomtextureheight != bloomtextureheight
6007 || r_bloomstate.texturetype != textype
6008 || r_bloomstate.viewfbo != r_viewfbo.integer)
6010 if (r_bloomstate.texture_bloom)
6011 R_FreeTexture(r_bloomstate.texture_bloom);
6012 r_bloomstate.texture_bloom = NULL;
6013 if (r_bloomstate.texture_screen)
6014 R_FreeTexture(r_bloomstate.texture_screen);
6015 r_bloomstate.texture_screen = NULL;
6016 if (r_bloomstate.fbo_framebuffer)
6017 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6018 r_bloomstate.fbo_framebuffer = 0;
6019 if (r_bloomstate.texture_framebuffercolor)
6020 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6021 r_bloomstate.texture_framebuffercolor = NULL;
6022 if (r_bloomstate.texture_framebufferdepth)
6023 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6024 r_bloomstate.texture_framebufferdepth = NULL;
6025 r_bloomstate.screentexturewidth = screentexturewidth;
6026 r_bloomstate.screentextureheight = screentextureheight;
6027 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6028 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);
6029 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6031 // FIXME: choose depth bits based on a cvar
6032 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6033 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);
6034 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6035 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6037 // render depth into one texture and normalmap into the other
6041 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6042 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6043 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6044 if (status != GL_FRAMEBUFFER_COMPLETE)
6045 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6049 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6050 r_bloomstate.bloomtextureheight = bloomtextureheight;
6051 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6052 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);
6053 r_bloomstate.viewfbo = r_viewfbo.integer;
6054 r_bloomstate.texturetype = textype;
6057 // when doing a reduced render (HDR) we want to use a smaller area
6058 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6059 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6060 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6061 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6062 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6064 // set up a texcoord array for the full resolution screen image
6065 // (we have to keep this around to copy back during final render)
6066 r_bloomstate.screentexcoord2f[0] = 0;
6067 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6068 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6069 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6070 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6071 r_bloomstate.screentexcoord2f[5] = 0;
6072 r_bloomstate.screentexcoord2f[6] = 0;
6073 r_bloomstate.screentexcoord2f[7] = 0;
6075 // set up a texcoord array for the reduced resolution bloom image
6076 // (which will be additive blended over the screen image)
6077 r_bloomstate.bloomtexcoord2f[0] = 0;
6078 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6079 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6080 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6081 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6082 r_bloomstate.bloomtexcoord2f[5] = 0;
6083 r_bloomstate.bloomtexcoord2f[6] = 0;
6084 r_bloomstate.bloomtexcoord2f[7] = 0;
6086 switch(vid.renderpath)
6088 case RENDERPATH_GL11:
6089 case RENDERPATH_GL13:
6090 case RENDERPATH_GL20:
6091 case RENDERPATH_SOFT:
6092 case RENDERPATH_GLES1:
6093 case RENDERPATH_GLES2:
6095 case RENDERPATH_D3D9:
6096 case RENDERPATH_D3D10:
6097 case RENDERPATH_D3D11:
6100 for (i = 0;i < 4;i++)
6102 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6103 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6104 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6105 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6111 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6113 r_bloomstate.enabled = true;
6114 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6117 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);
6119 if (r_bloomstate.fbo_framebuffer)
6120 r_refdef.view.clear = true;
6123 void R_Bloom_CopyBloomTexture(float colorscale)
6125 r_refdef.stats.bloom++;
6127 // scale down screen texture to the bloom texture size
6129 R_Mesh_SetMainRenderTargets();
6130 R_SetViewport(&r_bloomstate.viewport);
6131 GL_BlendFunc(GL_ONE, GL_ZERO);
6132 GL_Color(colorscale, colorscale, colorscale, 1);
6133 // 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...
6134 switch(vid.renderpath)
6136 case RENDERPATH_GL11:
6137 case RENDERPATH_GL13:
6138 case RENDERPATH_GL20:
6139 case RENDERPATH_GLES1:
6140 case RENDERPATH_GLES2:
6141 case RENDERPATH_SOFT:
6142 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6144 case RENDERPATH_D3D9:
6145 case RENDERPATH_D3D10:
6146 case RENDERPATH_D3D11:
6147 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6150 // TODO: do boxfilter scale-down in shader?
6151 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6152 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6153 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6155 // we now have a bloom image in the framebuffer
6156 // copy it into the bloom image texture for later processing
6157 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);
6158 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6161 void R_Bloom_CopyHDRTexture(void)
6163 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);
6164 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6167 void R_Bloom_MakeTexture(void)
6170 float xoffset, yoffset, r, brighten;
6172 r_refdef.stats.bloom++;
6174 R_ResetViewRendering2D();
6176 // we have a bloom image in the framebuffer
6178 R_SetViewport(&r_bloomstate.viewport);
6180 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6183 r = bound(0, r_bloom_colorexponent.value / x, 1);
6184 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6186 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6187 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6188 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6189 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6191 // copy the vertically blurred bloom view to a texture
6192 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);
6193 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6196 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6197 brighten = r_bloom_brighten.value;
6198 if (r_bloomstate.hdr)
6199 brighten *= r_hdr_range.value;
6200 brighten = sqrt(brighten);
6202 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6203 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6205 for (dir = 0;dir < 2;dir++)
6207 // blend on at multiple vertical offsets to achieve a vertical blur
6208 // TODO: do offset blends using GLSL
6209 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6210 GL_BlendFunc(GL_ONE, GL_ZERO);
6211 for (x = -range;x <= range;x++)
6213 if (!dir){xoffset = 0;yoffset = x;}
6214 else {xoffset = x;yoffset = 0;}
6215 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6216 yoffset /= (float)r_bloomstate.bloomtextureheight;
6217 // compute a texcoord array with the specified x and y offset
6218 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6219 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6220 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6221 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6222 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6223 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6224 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6225 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6226 // this r value looks like a 'dot' particle, fading sharply to
6227 // black at the edges
6228 // (probably not realistic but looks good enough)
6229 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6230 //r = brighten/(range*2+1);
6231 r = brighten / (range * 2 + 1);
6233 r *= (1 - x*x/(float)(range*range));
6234 GL_Color(r, r, r, 1);
6235 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6236 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6237 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6238 GL_BlendFunc(GL_ONE, GL_ONE);
6241 // copy the vertically blurred bloom view to a texture
6242 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);
6243 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6247 void R_HDR_RenderBloomTexture(void)
6249 int oldwidth, oldheight;
6250 float oldcolorscale;
6251 qboolean oldwaterstate;
6253 oldwaterstate = r_waterstate.enabled;
6254 oldcolorscale = r_refdef.view.colorscale;
6255 oldwidth = r_refdef.view.width;
6256 oldheight = r_refdef.view.height;
6257 r_refdef.view.width = r_bloomstate.bloomwidth;
6258 r_refdef.view.height = r_bloomstate.bloomheight;
6260 if(r_hdr.integer < 2)
6261 r_waterstate.enabled = false;
6263 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6264 // TODO: add exposure compensation features
6265 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6267 r_refdef.view.showdebug = false;
6268 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6270 R_ResetViewRendering3D();
6272 R_ClearScreen(r_refdef.fogenabled);
6273 if (r_timereport_active)
6274 R_TimeReport("HDRclear");
6277 if (r_timereport_active)
6278 R_TimeReport("visibility");
6280 // only do secondary renders with HDR if r_hdr is 2 or higher
6281 r_waterstate.numwaterplanes = 0;
6282 if (r_waterstate.enabled)
6283 R_RenderWaterPlanes();
6285 r_refdef.view.showdebug = true;
6287 r_waterstate.numwaterplanes = 0;
6289 R_ResetViewRendering2D();
6291 R_Bloom_CopyHDRTexture();
6292 R_Bloom_MakeTexture();
6294 // restore the view settings
6295 r_waterstate.enabled = oldwaterstate;
6296 r_refdef.view.width = oldwidth;
6297 r_refdef.view.height = oldheight;
6298 r_refdef.view.colorscale = oldcolorscale;
6300 R_ResetViewRendering3D();
6302 R_ClearScreen(r_refdef.fogenabled);
6303 if (r_timereport_active)
6304 R_TimeReport("viewclear");
6307 static void R_BlendView(void)
6309 unsigned int permutation;
6310 float uservecs[4][4];
6312 switch (vid.renderpath)
6314 case RENDERPATH_GL20:
6315 case RENDERPATH_D3D9:
6316 case RENDERPATH_D3D10:
6317 case RENDERPATH_D3D11:
6318 case RENDERPATH_SOFT:
6319 case RENDERPATH_GLES2:
6321 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6322 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6323 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6324 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6325 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6327 if (r_bloomstate.texture_screen)
6329 // make sure the buffer is available
6330 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6332 R_ResetViewRendering2D();
6333 R_Mesh_SetMainRenderTargets();
6335 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6337 // declare variables
6338 float blur_factor, blur_mouseaccel, blur_velocity;
6339 static float blur_average;
6340 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6342 // set a goal for the factoring
6343 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6344 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6345 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6346 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6347 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6348 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6350 // from the goal, pick an averaged value between goal and last value
6351 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6352 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6354 // enforce minimum amount of blur
6355 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6357 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6359 // calculate values into a standard alpha
6360 cl.motionbluralpha = 1 - exp(-
6362 (r_motionblur.value * blur_factor / 80)
6364 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6367 max(0.0001, cl.time - cl.oldtime) // fps independent
6370 // randomization for the blur value to combat persistent ghosting
6371 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6372 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6375 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6377 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6378 GL_Color(1, 1, 1, cl.motionbluralpha);
6379 switch(vid.renderpath)
6381 case RENDERPATH_GL11:
6382 case RENDERPATH_GL13:
6383 case RENDERPATH_GL20:
6384 case RENDERPATH_GLES1:
6385 case RENDERPATH_GLES2:
6386 case RENDERPATH_SOFT:
6387 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6389 case RENDERPATH_D3D9:
6390 case RENDERPATH_D3D10:
6391 case RENDERPATH_D3D11:
6392 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6395 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6396 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6397 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6400 // updates old view angles for next pass
6401 VectorCopy(cl.viewangles, blur_oldangles);
6404 // copy view into the screen texture
6405 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);
6406 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6408 else if (!r_bloomstate.texture_bloom)
6410 // we may still have to do view tint...
6411 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6413 // apply a color tint to the whole view
6414 R_ResetViewRendering2D();
6415 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6416 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6417 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6418 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6419 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6421 break; // no screen processing, no bloom, skip it
6424 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6426 // render simple bloom effect
6427 // copy the screen and shrink it and darken it for the bloom process
6428 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6429 // make the bloom texture
6430 R_Bloom_MakeTexture();
6433 #if _MSC_VER >= 1400
6434 #define sscanf sscanf_s
6436 memset(uservecs, 0, sizeof(uservecs));
6437 if (r_glsl_postprocess_uservec1_enable.integer)
6438 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6439 if (r_glsl_postprocess_uservec2_enable.integer)
6440 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6441 if (r_glsl_postprocess_uservec3_enable.integer)
6442 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6443 if (r_glsl_postprocess_uservec4_enable.integer)
6444 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6446 R_ResetViewRendering2D();
6447 GL_Color(1, 1, 1, 1);
6448 GL_BlendFunc(GL_ONE, GL_ZERO);
6450 switch(vid.renderpath)
6452 case RENDERPATH_GL20:
6453 case RENDERPATH_GLES2:
6454 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6455 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6456 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6457 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6458 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6459 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]);
6460 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6461 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]);
6462 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]);
6463 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]);
6464 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]);
6465 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6466 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6467 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);
6469 case RENDERPATH_D3D9:
6471 // 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...
6472 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6473 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6474 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6475 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6476 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6477 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6478 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6479 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6480 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6481 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6482 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6483 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6484 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6485 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6488 case RENDERPATH_D3D10:
6489 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6491 case RENDERPATH_D3D11:
6492 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6494 case RENDERPATH_SOFT:
6495 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6496 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6497 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6498 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6499 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6500 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6501 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6502 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6503 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6504 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6505 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6506 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6507 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6508 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6513 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6514 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6516 case RENDERPATH_GL11:
6517 case RENDERPATH_GL13:
6518 case RENDERPATH_GLES1:
6519 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6521 // apply a color tint to the whole view
6522 R_ResetViewRendering2D();
6523 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6524 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6525 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6526 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6527 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6533 matrix4x4_t r_waterscrollmatrix;
6535 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6537 if (r_refdef.fog_density)
6539 r_refdef.fogcolor[0] = r_refdef.fog_red;
6540 r_refdef.fogcolor[1] = r_refdef.fog_green;
6541 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6543 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6544 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6545 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6546 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6550 VectorCopy(r_refdef.fogcolor, fogvec);
6551 // color.rgb *= ContrastBoost * SceneBrightness;
6552 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6553 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6554 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6555 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6560 void R_UpdateVariables(void)
6564 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6566 r_refdef.farclip = r_farclip_base.value;
6567 if (r_refdef.scene.worldmodel)
6568 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6569 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6571 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6572 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6573 r_refdef.polygonfactor = 0;
6574 r_refdef.polygonoffset = 0;
6575 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6576 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6578 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6579 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6580 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6581 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6582 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6583 if (FAKELIGHT_ENABLED)
6585 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6587 if (r_showsurfaces.integer)
6589 r_refdef.scene.rtworld = false;
6590 r_refdef.scene.rtworldshadows = false;
6591 r_refdef.scene.rtdlight = false;
6592 r_refdef.scene.rtdlightshadows = false;
6593 r_refdef.lightmapintensity = 0;
6596 if (gamemode == GAME_NEHAHRA)
6598 if (gl_fogenable.integer)
6600 r_refdef.oldgl_fogenable = true;
6601 r_refdef.fog_density = gl_fogdensity.value;
6602 r_refdef.fog_red = gl_fogred.value;
6603 r_refdef.fog_green = gl_foggreen.value;
6604 r_refdef.fog_blue = gl_fogblue.value;
6605 r_refdef.fog_alpha = 1;
6606 r_refdef.fog_start = 0;
6607 r_refdef.fog_end = gl_skyclip.value;
6608 r_refdef.fog_height = 1<<30;
6609 r_refdef.fog_fadedepth = 128;
6611 else if (r_refdef.oldgl_fogenable)
6613 r_refdef.oldgl_fogenable = false;
6614 r_refdef.fog_density = 0;
6615 r_refdef.fog_red = 0;
6616 r_refdef.fog_green = 0;
6617 r_refdef.fog_blue = 0;
6618 r_refdef.fog_alpha = 0;
6619 r_refdef.fog_start = 0;
6620 r_refdef.fog_end = 0;
6621 r_refdef.fog_height = 1<<30;
6622 r_refdef.fog_fadedepth = 128;
6626 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6627 r_refdef.fog_start = max(0, r_refdef.fog_start);
6628 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6630 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6632 if (r_refdef.fog_density && r_drawfog.integer)
6634 r_refdef.fogenabled = true;
6635 // this is the point where the fog reaches 0.9986 alpha, which we
6636 // consider a good enough cutoff point for the texture
6637 // (0.9986 * 256 == 255.6)
6638 if (r_fog_exp2.integer)
6639 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6641 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6642 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6643 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6644 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6645 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6646 R_BuildFogHeightTexture();
6647 // fog color was already set
6648 // update the fog texture
6649 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)
6650 R_BuildFogTexture();
6651 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6652 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6655 r_refdef.fogenabled = false;
6657 switch(vid.renderpath)
6659 case RENDERPATH_GL20:
6660 case RENDERPATH_D3D9:
6661 case RENDERPATH_D3D10:
6662 case RENDERPATH_D3D11:
6663 case RENDERPATH_SOFT:
6664 case RENDERPATH_GLES2:
6665 if(v_glslgamma.integer && !vid_gammatables_trivial)
6667 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6669 // build GLSL gamma texture
6670 #define RAMPWIDTH 256
6671 unsigned short ramp[RAMPWIDTH * 3];
6672 unsigned char rampbgr[RAMPWIDTH][4];
6675 r_texture_gammaramps_serial = vid_gammatables_serial;
6677 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6678 for(i = 0; i < RAMPWIDTH; ++i)
6680 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6681 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6682 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6685 if (r_texture_gammaramps)
6687 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6691 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6697 // remove GLSL gamma texture
6700 case RENDERPATH_GL11:
6701 case RENDERPATH_GL13:
6702 case RENDERPATH_GLES1:
6707 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6708 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6714 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6715 if( scenetype != r_currentscenetype ) {
6716 // store the old scenetype
6717 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6718 r_currentscenetype = scenetype;
6719 // move in the new scene
6720 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6729 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6731 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6732 if( scenetype == r_currentscenetype ) {
6733 return &r_refdef.scene;
6735 return &r_scenes_store[ scenetype ];
6739 int R_SortEntities_Compare(const void *ap, const void *bp)
6741 const entity_render_t *a = *(const entity_render_t **)ap;
6742 const entity_render_t *b = *(const entity_render_t **)bp;
6745 if(a->model < b->model)
6747 if(a->model > b->model)
6751 // TODO possibly calculate the REAL skinnum here first using
6753 if(a->skinnum < b->skinnum)
6755 if(a->skinnum > b->skinnum)
6758 // everything we compared is equal
6761 void R_SortEntities(void)
6763 // below or equal 2 ents, sorting never gains anything
6764 if(r_refdef.scene.numentities <= 2)
6767 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6775 int dpsoftrast_test;
6776 extern void R_Shadow_UpdateBounceGridTexture(void);
6777 extern cvar_t r_shadow_bouncegrid;
6778 void R_RenderView(void)
6780 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6782 dpsoftrast_test = r_test.integer;
6784 if (r_timereport_active)
6785 R_TimeReport("start");
6786 r_textureframe++; // used only by R_GetCurrentTexture
6787 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6789 if(R_CompileShader_CheckStaticParms())
6792 if (!r_drawentities.integer)
6793 r_refdef.scene.numentities = 0;
6794 else if (r_sortentities.integer)
6797 R_AnimCache_ClearCache();
6798 R_FrameData_NewFrame();
6800 /* adjust for stereo display */
6801 if(R_Stereo_Active())
6803 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);
6804 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6807 if (r_refdef.view.isoverlay)
6809 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6810 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6811 R_TimeReport("depthclear");
6813 r_refdef.view.showdebug = false;
6815 r_waterstate.enabled = false;
6816 r_waterstate.numwaterplanes = 0;
6820 r_refdef.view.matrix = originalmatrix;
6826 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6828 r_refdef.view.matrix = originalmatrix;
6829 return; //Host_Error ("R_RenderView: NULL worldmodel");
6832 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6834 R_RenderView_UpdateViewVectors();
6836 R_Shadow_UpdateWorldLightSelection();
6838 R_Bloom_StartFrame();
6839 R_Water_StartFrame();
6842 if (r_timereport_active)
6843 R_TimeReport("viewsetup");
6845 R_ResetViewRendering3D();
6847 if (r_refdef.view.clear || r_refdef.fogenabled)
6849 R_ClearScreen(r_refdef.fogenabled);
6850 if (r_timereport_active)
6851 R_TimeReport("viewclear");
6853 r_refdef.view.clear = true;
6855 // this produces a bloom texture to be used in R_BlendView() later
6856 if (r_bloomstate.hdr)
6858 R_HDR_RenderBloomTexture();
6859 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6860 r_textureframe++; // used only by R_GetCurrentTexture
6863 r_refdef.view.showdebug = true;
6866 if (r_timereport_active)
6867 R_TimeReport("visibility");
6869 R_Shadow_UpdateBounceGridTexture();
6870 if (r_timereport_active && r_shadow_bouncegrid.integer)
6871 R_TimeReport("bouncegrid");
6873 r_waterstate.numwaterplanes = 0;
6874 if (r_waterstate.enabled)
6875 R_RenderWaterPlanes();
6878 r_waterstate.numwaterplanes = 0;
6881 if (r_timereport_active)
6882 R_TimeReport("blendview");
6884 GL_Scissor(0, 0, vid.width, vid.height);
6885 GL_ScissorTest(false);
6887 r_refdef.view.matrix = originalmatrix;
6892 void R_RenderWaterPlanes(void)
6894 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6896 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6897 if (r_timereport_active)
6898 R_TimeReport("waterworld");
6901 // don't let sound skip if going slow
6902 if (r_refdef.scene.extraupdate)
6905 R_DrawModelsAddWaterPlanes();
6906 if (r_timereport_active)
6907 R_TimeReport("watermodels");
6909 if (r_waterstate.numwaterplanes)
6911 R_Water_ProcessPlanes();
6912 if (r_timereport_active)
6913 R_TimeReport("waterscenes");
6917 extern void R_DrawLightningBeams (void);
6918 extern void VM_CL_AddPolygonsToMeshQueue (void);
6919 extern void R_DrawPortals (void);
6920 extern cvar_t cl_locs_show;
6921 static void R_DrawLocs(void);
6922 static void R_DrawEntityBBoxes(void);
6923 static void R_DrawModelDecals(void);
6924 extern void R_DrawModelShadows(void);
6925 extern void R_DrawModelShadowMaps(void);
6926 extern cvar_t cl_decals_newsystem;
6927 extern qboolean r_shadow_usingdeferredprepass;
6928 void R_RenderScene(void)
6930 qboolean shadowmapping = false;
6932 if (r_timereport_active)
6933 R_TimeReport("beginscene");
6935 r_refdef.stats.renders++;
6939 // don't let sound skip if going slow
6940 if (r_refdef.scene.extraupdate)
6943 R_MeshQueue_BeginScene();
6947 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);
6949 if (r_timereport_active)
6950 R_TimeReport("skystartframe");
6952 if (cl.csqc_vidvars.drawworld)
6954 // don't let sound skip if going slow
6955 if (r_refdef.scene.extraupdate)
6958 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6960 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6961 if (r_timereport_active)
6962 R_TimeReport("worldsky");
6965 if (R_DrawBrushModelsSky() && r_timereport_active)
6966 R_TimeReport("bmodelsky");
6968 if (skyrendermasked && skyrenderlater)
6970 // we have to force off the water clipping plane while rendering sky
6974 if (r_timereport_active)
6975 R_TimeReport("sky");
6979 R_AnimCache_CacheVisibleEntities();
6980 if (r_timereport_active)
6981 R_TimeReport("animation");
6983 R_Shadow_PrepareLights();
6984 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6985 R_Shadow_PrepareModelShadows();
6986 if (r_timereport_active)
6987 R_TimeReport("preparelights");
6989 if (R_Shadow_ShadowMappingEnabled())
6990 shadowmapping = true;
6992 if (r_shadow_usingdeferredprepass)
6993 R_Shadow_DrawPrepass();
6995 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6997 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6998 if (r_timereport_active)
6999 R_TimeReport("worlddepth");
7001 if (r_depthfirst.integer >= 2)
7003 R_DrawModelsDepth();
7004 if (r_timereport_active)
7005 R_TimeReport("modeldepth");
7008 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7010 R_DrawModelShadowMaps();
7011 R_ResetViewRendering3D();
7012 // don't let sound skip if going slow
7013 if (r_refdef.scene.extraupdate)
7017 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7019 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7020 if (r_timereport_active)
7021 R_TimeReport("world");
7024 // don't let sound skip if going slow
7025 if (r_refdef.scene.extraupdate)
7029 if (r_timereport_active)
7030 R_TimeReport("models");
7032 // don't let sound skip if going slow
7033 if (r_refdef.scene.extraupdate)
7036 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7038 R_DrawModelShadows();
7039 R_ResetViewRendering3D();
7040 // don't let sound skip if going slow
7041 if (r_refdef.scene.extraupdate)
7045 if (!r_shadow_usingdeferredprepass)
7047 R_Shadow_DrawLights();
7048 if (r_timereport_active)
7049 R_TimeReport("rtlights");
7052 // don't let sound skip if going slow
7053 if (r_refdef.scene.extraupdate)
7056 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7058 R_DrawModelShadows();
7059 R_ResetViewRendering3D();
7060 // don't let sound skip if going slow
7061 if (r_refdef.scene.extraupdate)
7065 if (cl.csqc_vidvars.drawworld)
7067 if (cl_decals_newsystem.integer)
7069 R_DrawModelDecals();
7070 if (r_timereport_active)
7071 R_TimeReport("modeldecals");
7076 if (r_timereport_active)
7077 R_TimeReport("decals");
7081 if (r_timereport_active)
7082 R_TimeReport("particles");
7085 if (r_timereport_active)
7086 R_TimeReport("explosions");
7088 R_DrawLightningBeams();
7089 if (r_timereport_active)
7090 R_TimeReport("lightning");
7093 VM_CL_AddPolygonsToMeshQueue();
7095 if (r_refdef.view.showdebug)
7097 if (cl_locs_show.integer)
7100 if (r_timereport_active)
7101 R_TimeReport("showlocs");
7104 if (r_drawportals.integer)
7107 if (r_timereport_active)
7108 R_TimeReport("portals");
7111 if (r_showbboxes.value > 0)
7113 R_DrawEntityBBoxes();
7114 if (r_timereport_active)
7115 R_TimeReport("bboxes");
7119 if (r_transparent.integer)
7121 R_MeshQueue_RenderTransparent();
7122 if (r_timereport_active)
7123 R_TimeReport("drawtrans");
7126 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))
7128 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7129 if (r_timereport_active)
7130 R_TimeReport("worlddebug");
7131 R_DrawModelsDebug();
7132 if (r_timereport_active)
7133 R_TimeReport("modeldebug");
7136 if (cl.csqc_vidvars.drawworld)
7138 R_Shadow_DrawCoronas();
7139 if (r_timereport_active)
7140 R_TimeReport("coronas");
7145 GL_DepthTest(false);
7146 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7147 GL_Color(1, 1, 1, 1);
7148 qglBegin(GL_POLYGON);
7149 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7150 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7151 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7152 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7154 qglBegin(GL_POLYGON);
7155 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]);
7156 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]);
7157 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]);
7158 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]);
7160 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7164 // don't let sound skip if going slow
7165 if (r_refdef.scene.extraupdate)
7168 R_ResetViewRendering2D();
7171 static const unsigned short bboxelements[36] =
7181 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7184 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7186 RSurf_ActiveWorldEntity();
7188 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7189 GL_DepthMask(false);
7190 GL_DepthRange(0, 1);
7191 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7192 // R_Mesh_ResetTextureState();
7194 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7195 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7196 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7197 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7198 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7199 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7200 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7201 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7202 R_FillColors(color4f, 8, cr, cg, cb, ca);
7203 if (r_refdef.fogenabled)
7205 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7207 f1 = RSurf_FogVertex(v);
7209 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7210 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7211 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7214 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7215 R_Mesh_ResetTextureState();
7216 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7217 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7220 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7224 prvm_edict_t *edict;
7225 prvm_prog_t *prog_save = prog;
7227 // this function draws bounding boxes of server entities
7231 GL_CullFace(GL_NONE);
7232 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7236 for (i = 0;i < numsurfaces;i++)
7238 edict = PRVM_EDICT_NUM(surfacelist[i]);
7239 switch ((int)PRVM_serveredictfloat(edict, solid))
7241 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7242 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7243 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7244 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7245 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7246 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7248 color[3] *= r_showbboxes.value;
7249 color[3] = bound(0, color[3], 1);
7250 GL_DepthTest(!r_showdisabledepthtest.integer);
7251 GL_CullFace(r_refdef.view.cullface_front);
7252 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7258 static void R_DrawEntityBBoxes(void)
7261 prvm_edict_t *edict;
7263 prvm_prog_t *prog_save = prog;
7265 // this function draws bounding boxes of server entities
7271 for (i = 0;i < prog->num_edicts;i++)
7273 edict = PRVM_EDICT_NUM(i);
7274 if (edict->priv.server->free)
7276 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7277 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7279 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7281 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7282 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7288 static const int nomodelelement3i[24] =
7300 static const unsigned short nomodelelement3s[24] =
7312 static const float nomodelvertex3f[6*3] =
7322 static const float nomodelcolor4f[6*4] =
7324 0.0f, 0.0f, 0.5f, 1.0f,
7325 0.0f, 0.0f, 0.5f, 1.0f,
7326 0.0f, 0.5f, 0.0f, 1.0f,
7327 0.0f, 0.5f, 0.0f, 1.0f,
7328 0.5f, 0.0f, 0.0f, 1.0f,
7329 0.5f, 0.0f, 0.0f, 1.0f
7332 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7338 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);
7340 // this is only called once per entity so numsurfaces is always 1, and
7341 // surfacelist is always {0}, so this code does not handle batches
7343 if (rsurface.ent_flags & RENDER_ADDITIVE)
7345 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7346 GL_DepthMask(false);
7348 else if (rsurface.colormod[3] < 1)
7350 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7351 GL_DepthMask(false);
7355 GL_BlendFunc(GL_ONE, GL_ZERO);
7358 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7359 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7360 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7361 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7362 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7363 for (i = 0, c = color4f;i < 6;i++, c += 4)
7365 c[0] *= rsurface.colormod[0];
7366 c[1] *= rsurface.colormod[1];
7367 c[2] *= rsurface.colormod[2];
7368 c[3] *= rsurface.colormod[3];
7370 if (r_refdef.fogenabled)
7372 for (i = 0, c = color4f;i < 6;i++, c += 4)
7374 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7376 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7377 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7378 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7381 // R_Mesh_ResetTextureState();
7382 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7383 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7384 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7387 void R_DrawNoModel(entity_render_t *ent)
7390 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7391 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7392 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7394 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7397 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7399 vec3_t right1, right2, diff, normal;
7401 VectorSubtract (org2, org1, normal);
7403 // calculate 'right' vector for start
7404 VectorSubtract (r_refdef.view.origin, org1, diff);
7405 CrossProduct (normal, diff, right1);
7406 VectorNormalize (right1);
7408 // calculate 'right' vector for end
7409 VectorSubtract (r_refdef.view.origin, org2, diff);
7410 CrossProduct (normal, diff, right2);
7411 VectorNormalize (right2);
7413 vert[ 0] = org1[0] + width * right1[0];
7414 vert[ 1] = org1[1] + width * right1[1];
7415 vert[ 2] = org1[2] + width * right1[2];
7416 vert[ 3] = org1[0] - width * right1[0];
7417 vert[ 4] = org1[1] - width * right1[1];
7418 vert[ 5] = org1[2] - width * right1[2];
7419 vert[ 6] = org2[0] - width * right2[0];
7420 vert[ 7] = org2[1] - width * right2[1];
7421 vert[ 8] = org2[2] - width * right2[2];
7422 vert[ 9] = org2[0] + width * right2[0];
7423 vert[10] = org2[1] + width * right2[1];
7424 vert[11] = org2[2] + width * right2[2];
7427 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)
7429 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7430 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7431 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7432 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7433 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7434 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7435 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7436 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7437 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7438 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7439 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7440 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7443 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7448 VectorSet(v, x, y, z);
7449 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7450 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7452 if (i == mesh->numvertices)
7454 if (mesh->numvertices < mesh->maxvertices)
7456 VectorCopy(v, vertex3f);
7457 mesh->numvertices++;
7459 return mesh->numvertices;
7465 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7469 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7470 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7471 e = mesh->element3i + mesh->numtriangles * 3;
7472 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7474 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7475 if (mesh->numtriangles < mesh->maxtriangles)
7480 mesh->numtriangles++;
7482 element[1] = element[2];
7486 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7490 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7491 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7492 e = mesh->element3i + mesh->numtriangles * 3;
7493 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7495 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7496 if (mesh->numtriangles < mesh->maxtriangles)
7501 mesh->numtriangles++;
7503 element[1] = element[2];
7507 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7508 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7510 int planenum, planenum2;
7513 mplane_t *plane, *plane2;
7515 double temppoints[2][256*3];
7516 // figure out how large a bounding box we need to properly compute this brush
7518 for (w = 0;w < numplanes;w++)
7519 maxdist = max(maxdist, fabs(planes[w].dist));
7520 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7521 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7522 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7526 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7527 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7529 if (planenum2 == planenum)
7531 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);
7534 if (tempnumpoints < 3)
7536 // generate elements forming a triangle fan for this polygon
7537 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7541 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)
7543 texturelayer_t *layer;
7544 layer = t->currentlayers + t->currentnumlayers++;
7546 layer->depthmask = depthmask;
7547 layer->blendfunc1 = blendfunc1;
7548 layer->blendfunc2 = blendfunc2;
7549 layer->texture = texture;
7550 layer->texmatrix = *matrix;
7551 layer->color[0] = r;
7552 layer->color[1] = g;
7553 layer->color[2] = b;
7554 layer->color[3] = a;
7557 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7559 if(parms[0] == 0 && parms[1] == 0)
7561 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7562 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7567 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7570 index = parms[2] + rsurface.shadertime * parms[3];
7571 index -= floor(index);
7572 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7575 case Q3WAVEFUNC_NONE:
7576 case Q3WAVEFUNC_NOISE:
7577 case Q3WAVEFUNC_COUNT:
7580 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7581 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7582 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7583 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7584 case Q3WAVEFUNC_TRIANGLE:
7586 f = index - floor(index);
7599 f = parms[0] + parms[1] * f;
7600 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7601 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7605 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7611 matrix4x4_t matrix, temp;
7612 switch(tcmod->tcmod)
7616 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7617 matrix = r_waterscrollmatrix;
7619 matrix = identitymatrix;
7621 case Q3TCMOD_ENTITYTRANSLATE:
7622 // this is used in Q3 to allow the gamecode to control texcoord
7623 // scrolling on the entity, which is not supported in darkplaces yet.
7624 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7626 case Q3TCMOD_ROTATE:
7627 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7628 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7629 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7632 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7634 case Q3TCMOD_SCROLL:
7635 // extra care is needed because of precision breakdown with large values of time
7636 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7637 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7638 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7640 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7641 w = (int) tcmod->parms[0];
7642 h = (int) tcmod->parms[1];
7643 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7645 idx = (int) floor(f * w * h);
7646 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7648 case Q3TCMOD_STRETCH:
7649 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7650 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7652 case Q3TCMOD_TRANSFORM:
7653 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7654 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7655 VectorSet(tcmat + 6, 0 , 0 , 1);
7656 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7657 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7659 case Q3TCMOD_TURBULENT:
7660 // this is handled in the RSurf_PrepareVertices function
7661 matrix = identitymatrix;
7665 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7668 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7670 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7671 char name[MAX_QPATH];
7672 skinframe_t *skinframe;
7673 unsigned char pixels[296*194];
7674 strlcpy(cache->name, skinname, sizeof(cache->name));
7675 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7676 if (developer_loading.integer)
7677 Con_Printf("loading %s\n", name);
7678 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7679 if (!skinframe || !skinframe->base)
7682 fs_offset_t filesize;
7684 f = FS_LoadFile(name, tempmempool, true, &filesize);
7687 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7688 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7692 cache->skinframe = skinframe;
7695 texture_t *R_GetCurrentTexture(texture_t *t)
7698 const entity_render_t *ent = rsurface.entity;
7699 dp_model_t *model = ent->model;
7700 q3shaderinfo_layer_tcmod_t *tcmod;
7702 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7703 return t->currentframe;
7704 t->update_lastrenderframe = r_textureframe;
7705 t->update_lastrenderentity = (void *)ent;
7707 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7708 t->camera_entity = ent->entitynumber;
7710 t->camera_entity = 0;
7712 // switch to an alternate material if this is a q1bsp animated material
7714 texture_t *texture = t;
7715 int s = rsurface.ent_skinnum;
7716 if ((unsigned int)s >= (unsigned int)model->numskins)
7718 if (model->skinscenes)
7720 if (model->skinscenes[s].framecount > 1)
7721 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7723 s = model->skinscenes[s].firstframe;
7726 t = t + s * model->num_surfaces;
7729 // use an alternate animation if the entity's frame is not 0,
7730 // and only if the texture has an alternate animation
7731 if (rsurface.ent_alttextures && t->anim_total[1])
7732 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7734 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7736 texture->currentframe = t;
7739 // update currentskinframe to be a qw skin or animation frame
7740 if (rsurface.ent_qwskin >= 0)
7742 i = rsurface.ent_qwskin;
7743 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7745 r_qwskincache_size = cl.maxclients;
7747 Mem_Free(r_qwskincache);
7748 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7750 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7751 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7752 t->currentskinframe = r_qwskincache[i].skinframe;
7753 if (t->currentskinframe == NULL)
7754 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7756 else if (t->numskinframes >= 2)
7757 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7758 if (t->backgroundnumskinframes >= 2)
7759 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7761 t->currentmaterialflags = t->basematerialflags;
7762 t->currentalpha = rsurface.colormod[3];
7763 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7764 t->currentalpha *= r_wateralpha.value;
7765 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7766 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7767 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7768 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7769 if (!(rsurface.ent_flags & RENDER_LIGHT))
7770 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7771 else if (FAKELIGHT_ENABLED)
7773 // no modellight if using fakelight for the map
7775 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7777 // pick a model lighting mode
7778 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7779 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7781 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7783 if (rsurface.ent_flags & RENDER_ADDITIVE)
7784 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7785 else if (t->currentalpha < 1)
7786 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7787 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7788 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7789 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7790 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7791 if (t->backgroundnumskinframes)
7792 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7793 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7795 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7796 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7799 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7800 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7802 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7803 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7805 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7806 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7808 // there is no tcmod
7809 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7811 t->currenttexmatrix = r_waterscrollmatrix;
7812 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7814 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7816 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7817 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7820 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7821 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7822 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7823 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7825 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7826 if (t->currentskinframe->qpixels)
7827 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7828 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7829 if (!t->basetexture)
7830 t->basetexture = r_texture_notexture;
7831 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7832 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7833 t->nmaptexture = t->currentskinframe->nmap;
7834 if (!t->nmaptexture)
7835 t->nmaptexture = r_texture_blanknormalmap;
7836 t->glosstexture = r_texture_black;
7837 t->glowtexture = t->currentskinframe->glow;
7838 t->fogtexture = t->currentskinframe->fog;
7839 t->reflectmasktexture = t->currentskinframe->reflect;
7840 if (t->backgroundnumskinframes)
7842 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7843 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7844 t->backgroundglosstexture = r_texture_black;
7845 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7846 if (!t->backgroundnmaptexture)
7847 t->backgroundnmaptexture = r_texture_blanknormalmap;
7851 t->backgroundbasetexture = r_texture_white;
7852 t->backgroundnmaptexture = r_texture_blanknormalmap;
7853 t->backgroundglosstexture = r_texture_black;
7854 t->backgroundglowtexture = NULL;
7856 t->specularpower = r_shadow_glossexponent.value;
7857 // TODO: store reference values for these in the texture?
7858 t->specularscale = 0;
7859 if (r_shadow_gloss.integer > 0)
7861 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7863 if (r_shadow_glossintensity.value > 0)
7865 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7866 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7867 t->specularscale = r_shadow_glossintensity.value;
7870 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7872 t->glosstexture = r_texture_white;
7873 t->backgroundglosstexture = r_texture_white;
7874 t->specularscale = r_shadow_gloss2intensity.value;
7875 t->specularpower = r_shadow_gloss2exponent.value;
7878 t->specularscale *= t->specularscalemod;
7879 t->specularpower *= t->specularpowermod;
7880 t->rtlightambient = 0;
7882 // lightmaps mode looks bad with dlights using actual texturing, so turn
7883 // off the colormap and glossmap, but leave the normalmap on as it still
7884 // accurately represents the shading involved
7885 if (gl_lightmaps.integer)
7887 t->basetexture = r_texture_grey128;
7888 t->pantstexture = r_texture_black;
7889 t->shirttexture = r_texture_black;
7890 t->nmaptexture = r_texture_blanknormalmap;
7891 t->glosstexture = r_texture_black;
7892 t->glowtexture = NULL;
7893 t->fogtexture = NULL;
7894 t->reflectmasktexture = NULL;
7895 t->backgroundbasetexture = NULL;
7896 t->backgroundnmaptexture = r_texture_blanknormalmap;
7897 t->backgroundglosstexture = r_texture_black;
7898 t->backgroundglowtexture = NULL;
7899 t->specularscale = 0;
7900 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7903 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7904 VectorClear(t->dlightcolor);
7905 t->currentnumlayers = 0;
7906 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7908 int blendfunc1, blendfunc2;
7910 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7912 blendfunc1 = GL_SRC_ALPHA;
7913 blendfunc2 = GL_ONE;
7915 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7917 blendfunc1 = GL_SRC_ALPHA;
7918 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7920 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7922 blendfunc1 = t->customblendfunc[0];
7923 blendfunc2 = t->customblendfunc[1];
7927 blendfunc1 = GL_ONE;
7928 blendfunc2 = GL_ZERO;
7930 // don't colormod evilblend textures
7931 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7932 VectorSet(t->lightmapcolor, 1, 1, 1);
7933 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7934 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7936 // fullbright is not affected by r_refdef.lightmapintensity
7937 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]);
7938 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7939 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]);
7940 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7941 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]);
7945 vec3_t ambientcolor;
7947 // set the color tint used for lights affecting this surface
7948 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7950 // q3bsp has no lightmap updates, so the lightstylevalue that
7951 // would normally be baked into the lightmap must be
7952 // applied to the color
7953 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7954 if (model->type == mod_brushq3)
7955 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7956 colorscale *= r_refdef.lightmapintensity;
7957 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7958 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7959 // basic lit geometry
7960 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]);
7961 // add pants/shirt if needed
7962 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7963 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]);
7964 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7965 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]);
7966 // now add ambient passes if needed
7967 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7969 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]);
7970 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7971 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]);
7972 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7973 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]);
7976 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7977 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]);
7978 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7980 // if this is opaque use alpha blend which will darken the earlier
7983 // if this is an alpha blended material, all the earlier passes
7984 // were darkened by fog already, so we only need to add the fog
7985 // color ontop through the fog mask texture
7987 // if this is an additive blended material, all the earlier passes
7988 // were darkened by fog already, and we should not add fog color
7989 // (because the background was not darkened, there is no fog color
7990 // that was lost behind it).
7991 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]);
7995 return t->currentframe;
7998 rsurfacestate_t rsurface;
8000 void RSurf_ActiveWorldEntity(void)
8002 dp_model_t *model = r_refdef.scene.worldmodel;
8003 //if (rsurface.entity == r_refdef.scene.worldentity)
8005 rsurface.entity = r_refdef.scene.worldentity;
8006 rsurface.skeleton = NULL;
8007 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8008 rsurface.ent_skinnum = 0;
8009 rsurface.ent_qwskin = -1;
8010 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8011 rsurface.shadertime = r_refdef.scene.time;
8012 rsurface.matrix = identitymatrix;
8013 rsurface.inversematrix = identitymatrix;
8014 rsurface.matrixscale = 1;
8015 rsurface.inversematrixscale = 1;
8016 R_EntityMatrix(&identitymatrix);
8017 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8018 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8019 rsurface.fograngerecip = r_refdef.fograngerecip;
8020 rsurface.fogheightfade = r_refdef.fogheightfade;
8021 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8022 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8023 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8024 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8025 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8026 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8027 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8028 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8029 rsurface.colormod[3] = 1;
8030 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);
8031 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8032 rsurface.frameblend[0].lerp = 1;
8033 rsurface.ent_alttextures = false;
8034 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8035 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8036 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8037 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8038 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8039 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8040 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8041 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8042 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8043 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8044 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8045 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8046 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8047 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8048 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8049 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8050 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8051 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8052 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8053 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8054 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8055 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8056 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8057 rsurface.modelelement3i = model->surfmesh.data_element3i;
8058 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8059 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8060 rsurface.modelelement3s = model->surfmesh.data_element3s;
8061 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8062 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8063 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8064 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8065 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8066 rsurface.modelsurfaces = model->data_surfaces;
8067 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8068 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8069 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8070 rsurface.modelgeneratedvertex = false;
8071 rsurface.batchgeneratedvertex = false;
8072 rsurface.batchfirstvertex = 0;
8073 rsurface.batchnumvertices = 0;
8074 rsurface.batchfirsttriangle = 0;
8075 rsurface.batchnumtriangles = 0;
8076 rsurface.batchvertex3f = NULL;
8077 rsurface.batchvertex3f_vertexbuffer = NULL;
8078 rsurface.batchvertex3f_bufferoffset = 0;
8079 rsurface.batchsvector3f = NULL;
8080 rsurface.batchsvector3f_vertexbuffer = NULL;
8081 rsurface.batchsvector3f_bufferoffset = 0;
8082 rsurface.batchtvector3f = NULL;
8083 rsurface.batchtvector3f_vertexbuffer = NULL;
8084 rsurface.batchtvector3f_bufferoffset = 0;
8085 rsurface.batchnormal3f = NULL;
8086 rsurface.batchnormal3f_vertexbuffer = NULL;
8087 rsurface.batchnormal3f_bufferoffset = 0;
8088 rsurface.batchlightmapcolor4f = NULL;
8089 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8090 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8091 rsurface.batchtexcoordtexture2f = NULL;
8092 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8093 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8094 rsurface.batchtexcoordlightmap2f = NULL;
8095 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8096 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8097 rsurface.batchvertexmesh = NULL;
8098 rsurface.batchvertexmeshbuffer = NULL;
8099 rsurface.batchvertex3fbuffer = NULL;
8100 rsurface.batchelement3i = NULL;
8101 rsurface.batchelement3i_indexbuffer = NULL;
8102 rsurface.batchelement3i_bufferoffset = 0;
8103 rsurface.batchelement3s = NULL;
8104 rsurface.batchelement3s_indexbuffer = NULL;
8105 rsurface.batchelement3s_bufferoffset = 0;
8106 rsurface.passcolor4f = NULL;
8107 rsurface.passcolor4f_vertexbuffer = NULL;
8108 rsurface.passcolor4f_bufferoffset = 0;
8111 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8113 dp_model_t *model = ent->model;
8114 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8116 rsurface.entity = (entity_render_t *)ent;
8117 rsurface.skeleton = ent->skeleton;
8118 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8119 rsurface.ent_skinnum = ent->skinnum;
8120 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;
8121 rsurface.ent_flags = ent->flags;
8122 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8123 rsurface.matrix = ent->matrix;
8124 rsurface.inversematrix = ent->inversematrix;
8125 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8126 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8127 R_EntityMatrix(&rsurface.matrix);
8128 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8129 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8130 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8131 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8132 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8133 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8134 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8135 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8136 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8137 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8138 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8139 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8140 rsurface.colormod[3] = ent->alpha;
8141 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8142 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8143 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8144 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8145 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8146 if (ent->model->brush.submodel && !prepass)
8148 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8149 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8151 if (model->surfmesh.isanimated && model->AnimateVertices)
8153 if (ent->animcache_vertex3f)
8155 rsurface.modelvertex3f = ent->animcache_vertex3f;
8156 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8157 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8158 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8159 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8160 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8161 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8163 else if (wanttangents)
8165 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8166 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8167 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8168 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8169 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8170 rsurface.modelvertexmesh = NULL;
8171 rsurface.modelvertexmeshbuffer = NULL;
8172 rsurface.modelvertex3fbuffer = NULL;
8174 else if (wantnormals)
8176 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8177 rsurface.modelsvector3f = NULL;
8178 rsurface.modeltvector3f = NULL;
8179 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8180 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8181 rsurface.modelvertexmesh = NULL;
8182 rsurface.modelvertexmeshbuffer = NULL;
8183 rsurface.modelvertex3fbuffer = NULL;
8187 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8188 rsurface.modelsvector3f = NULL;
8189 rsurface.modeltvector3f = NULL;
8190 rsurface.modelnormal3f = NULL;
8191 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8192 rsurface.modelvertexmesh = NULL;
8193 rsurface.modelvertexmeshbuffer = NULL;
8194 rsurface.modelvertex3fbuffer = NULL;
8196 rsurface.modelvertex3f_vertexbuffer = 0;
8197 rsurface.modelvertex3f_bufferoffset = 0;
8198 rsurface.modelsvector3f_vertexbuffer = 0;
8199 rsurface.modelsvector3f_bufferoffset = 0;
8200 rsurface.modeltvector3f_vertexbuffer = 0;
8201 rsurface.modeltvector3f_bufferoffset = 0;
8202 rsurface.modelnormal3f_vertexbuffer = 0;
8203 rsurface.modelnormal3f_bufferoffset = 0;
8204 rsurface.modelgeneratedvertex = true;
8208 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8209 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8210 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8211 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8212 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8213 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8214 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8215 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8216 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8217 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8218 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8219 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8220 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8221 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8222 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8223 rsurface.modelgeneratedvertex = false;
8225 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8226 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8227 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8228 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8229 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8230 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8231 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8232 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8233 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8234 rsurface.modelelement3i = model->surfmesh.data_element3i;
8235 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8236 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8237 rsurface.modelelement3s = model->surfmesh.data_element3s;
8238 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8239 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8240 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8241 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8242 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8243 rsurface.modelsurfaces = model->data_surfaces;
8244 rsurface.batchgeneratedvertex = false;
8245 rsurface.batchfirstvertex = 0;
8246 rsurface.batchnumvertices = 0;
8247 rsurface.batchfirsttriangle = 0;
8248 rsurface.batchnumtriangles = 0;
8249 rsurface.batchvertex3f = NULL;
8250 rsurface.batchvertex3f_vertexbuffer = NULL;
8251 rsurface.batchvertex3f_bufferoffset = 0;
8252 rsurface.batchsvector3f = NULL;
8253 rsurface.batchsvector3f_vertexbuffer = NULL;
8254 rsurface.batchsvector3f_bufferoffset = 0;
8255 rsurface.batchtvector3f = NULL;
8256 rsurface.batchtvector3f_vertexbuffer = NULL;
8257 rsurface.batchtvector3f_bufferoffset = 0;
8258 rsurface.batchnormal3f = NULL;
8259 rsurface.batchnormal3f_vertexbuffer = NULL;
8260 rsurface.batchnormal3f_bufferoffset = 0;
8261 rsurface.batchlightmapcolor4f = NULL;
8262 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8263 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8264 rsurface.batchtexcoordtexture2f = NULL;
8265 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8266 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8267 rsurface.batchtexcoordlightmap2f = NULL;
8268 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8269 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8270 rsurface.batchvertexmesh = NULL;
8271 rsurface.batchvertexmeshbuffer = NULL;
8272 rsurface.batchvertex3fbuffer = NULL;
8273 rsurface.batchelement3i = NULL;
8274 rsurface.batchelement3i_indexbuffer = NULL;
8275 rsurface.batchelement3i_bufferoffset = 0;
8276 rsurface.batchelement3s = NULL;
8277 rsurface.batchelement3s_indexbuffer = NULL;
8278 rsurface.batchelement3s_bufferoffset = 0;
8279 rsurface.passcolor4f = NULL;
8280 rsurface.passcolor4f_vertexbuffer = NULL;
8281 rsurface.passcolor4f_bufferoffset = 0;
8284 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)
8286 rsurface.entity = r_refdef.scene.worldentity;
8287 rsurface.skeleton = NULL;
8288 rsurface.ent_skinnum = 0;
8289 rsurface.ent_qwskin = -1;
8290 rsurface.ent_flags = entflags;
8291 rsurface.shadertime = r_refdef.scene.time - shadertime;
8292 rsurface.modelnumvertices = numvertices;
8293 rsurface.modelnumtriangles = numtriangles;
8294 rsurface.matrix = *matrix;
8295 rsurface.inversematrix = *inversematrix;
8296 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8297 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8298 R_EntityMatrix(&rsurface.matrix);
8299 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8300 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8301 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8302 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8303 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8304 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8305 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8306 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8307 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8308 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8309 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8310 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8311 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);
8312 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8313 rsurface.frameblend[0].lerp = 1;
8314 rsurface.ent_alttextures = false;
8315 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8316 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8319 rsurface.modelvertex3f = (float *)vertex3f;
8320 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8321 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8322 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8324 else if (wantnormals)
8326 rsurface.modelvertex3f = (float *)vertex3f;
8327 rsurface.modelsvector3f = NULL;
8328 rsurface.modeltvector3f = NULL;
8329 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8333 rsurface.modelvertex3f = (float *)vertex3f;
8334 rsurface.modelsvector3f = NULL;
8335 rsurface.modeltvector3f = NULL;
8336 rsurface.modelnormal3f = NULL;
8338 rsurface.modelvertexmesh = NULL;
8339 rsurface.modelvertexmeshbuffer = NULL;
8340 rsurface.modelvertex3fbuffer = NULL;
8341 rsurface.modelvertex3f_vertexbuffer = 0;
8342 rsurface.modelvertex3f_bufferoffset = 0;
8343 rsurface.modelsvector3f_vertexbuffer = 0;
8344 rsurface.modelsvector3f_bufferoffset = 0;
8345 rsurface.modeltvector3f_vertexbuffer = 0;
8346 rsurface.modeltvector3f_bufferoffset = 0;
8347 rsurface.modelnormal3f_vertexbuffer = 0;
8348 rsurface.modelnormal3f_bufferoffset = 0;
8349 rsurface.modelgeneratedvertex = true;
8350 rsurface.modellightmapcolor4f = (float *)color4f;
8351 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8352 rsurface.modellightmapcolor4f_bufferoffset = 0;
8353 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8354 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8355 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8356 rsurface.modeltexcoordlightmap2f = NULL;
8357 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8358 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8359 rsurface.modelelement3i = (int *)element3i;
8360 rsurface.modelelement3i_indexbuffer = NULL;
8361 rsurface.modelelement3i_bufferoffset = 0;
8362 rsurface.modelelement3s = (unsigned short *)element3s;
8363 rsurface.modelelement3s_indexbuffer = NULL;
8364 rsurface.modelelement3s_bufferoffset = 0;
8365 rsurface.modellightmapoffsets = NULL;
8366 rsurface.modelsurfaces = NULL;
8367 rsurface.batchgeneratedvertex = false;
8368 rsurface.batchfirstvertex = 0;
8369 rsurface.batchnumvertices = 0;
8370 rsurface.batchfirsttriangle = 0;
8371 rsurface.batchnumtriangles = 0;
8372 rsurface.batchvertex3f = NULL;
8373 rsurface.batchvertex3f_vertexbuffer = NULL;
8374 rsurface.batchvertex3f_bufferoffset = 0;
8375 rsurface.batchsvector3f = NULL;
8376 rsurface.batchsvector3f_vertexbuffer = NULL;
8377 rsurface.batchsvector3f_bufferoffset = 0;
8378 rsurface.batchtvector3f = NULL;
8379 rsurface.batchtvector3f_vertexbuffer = NULL;
8380 rsurface.batchtvector3f_bufferoffset = 0;
8381 rsurface.batchnormal3f = NULL;
8382 rsurface.batchnormal3f_vertexbuffer = NULL;
8383 rsurface.batchnormal3f_bufferoffset = 0;
8384 rsurface.batchlightmapcolor4f = NULL;
8385 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8386 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8387 rsurface.batchtexcoordtexture2f = NULL;
8388 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8389 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8390 rsurface.batchtexcoordlightmap2f = NULL;
8391 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8392 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8393 rsurface.batchvertexmesh = NULL;
8394 rsurface.batchvertexmeshbuffer = NULL;
8395 rsurface.batchvertex3fbuffer = NULL;
8396 rsurface.batchelement3i = NULL;
8397 rsurface.batchelement3i_indexbuffer = NULL;
8398 rsurface.batchelement3i_bufferoffset = 0;
8399 rsurface.batchelement3s = NULL;
8400 rsurface.batchelement3s_indexbuffer = NULL;
8401 rsurface.batchelement3s_bufferoffset = 0;
8402 rsurface.passcolor4f = NULL;
8403 rsurface.passcolor4f_vertexbuffer = NULL;
8404 rsurface.passcolor4f_bufferoffset = 0;
8406 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8408 if ((wantnormals || wanttangents) && !normal3f)
8410 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8411 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8413 if (wanttangents && !svector3f)
8415 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8416 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8417 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8422 float RSurf_FogPoint(const float *v)
8424 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8425 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8426 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8427 float FogHeightFade = r_refdef.fogheightfade;
8429 unsigned int fogmasktableindex;
8430 if (r_refdef.fogplaneviewabove)
8431 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8433 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8434 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8435 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8438 float RSurf_FogVertex(const float *v)
8440 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8441 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8442 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8443 float FogHeightFade = rsurface.fogheightfade;
8445 unsigned int fogmasktableindex;
8446 if (r_refdef.fogplaneviewabove)
8447 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8449 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8450 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8451 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8454 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8457 for (i = 0;i < numelements;i++)
8458 outelement3i[i] = inelement3i[i] + adjust;
8461 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8462 extern cvar_t gl_vbo;
8463 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8471 int surfacefirsttriangle;
8472 int surfacenumtriangles;
8473 int surfacefirstvertex;
8474 int surfaceendvertex;
8475 int surfacenumvertices;
8476 int batchnumvertices;
8477 int batchnumtriangles;
8481 qboolean dynamicvertex;
8485 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8487 q3shaderinfo_deform_t *deform;
8488 const msurface_t *surface, *firstsurface;
8489 r_vertexmesh_t *vertexmesh;
8490 if (!texturenumsurfaces)
8492 // find vertex range of this surface batch
8494 firstsurface = texturesurfacelist[0];
8495 firsttriangle = firstsurface->num_firsttriangle;
8496 batchnumvertices = 0;
8497 batchnumtriangles = 0;
8498 firstvertex = endvertex = firstsurface->num_firstvertex;
8499 for (i = 0;i < texturenumsurfaces;i++)
8501 surface = texturesurfacelist[i];
8502 if (surface != firstsurface + i)
8504 surfacefirstvertex = surface->num_firstvertex;
8505 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8506 surfacenumvertices = surface->num_vertices;
8507 surfacenumtriangles = surface->num_triangles;
8508 if (firstvertex > surfacefirstvertex)
8509 firstvertex = surfacefirstvertex;
8510 if (endvertex < surfaceendvertex)
8511 endvertex = surfaceendvertex;
8512 batchnumvertices += surfacenumvertices;
8513 batchnumtriangles += surfacenumtriangles;
8516 // we now know the vertex range used, and if there are any gaps in it
8517 rsurface.batchfirstvertex = firstvertex;
8518 rsurface.batchnumvertices = endvertex - firstvertex;
8519 rsurface.batchfirsttriangle = firsttriangle;
8520 rsurface.batchnumtriangles = batchnumtriangles;
8522 // this variable holds flags for which properties have been updated that
8523 // may require regenerating vertexmesh array...
8526 // check if any dynamic vertex processing must occur
8527 dynamicvertex = false;
8529 // if there is a chance of animated vertex colors, it's a dynamic batch
8530 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8532 dynamicvertex = true;
8533 batchneed |= BATCHNEED_NOGAPS;
8534 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8537 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8539 switch (deform->deform)
8542 case Q3DEFORM_PROJECTIONSHADOW:
8543 case Q3DEFORM_TEXT0:
8544 case Q3DEFORM_TEXT1:
8545 case Q3DEFORM_TEXT2:
8546 case Q3DEFORM_TEXT3:
8547 case Q3DEFORM_TEXT4:
8548 case Q3DEFORM_TEXT5:
8549 case Q3DEFORM_TEXT6:
8550 case Q3DEFORM_TEXT7:
8553 case Q3DEFORM_AUTOSPRITE:
8554 dynamicvertex = true;
8555 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8556 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8558 case Q3DEFORM_AUTOSPRITE2:
8559 dynamicvertex = true;
8560 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8561 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8563 case Q3DEFORM_NORMAL:
8564 dynamicvertex = true;
8565 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8566 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8569 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8570 break; // if wavefunc is a nop, ignore this transform
8571 dynamicvertex = true;
8572 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8573 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8575 case Q3DEFORM_BULGE:
8576 dynamicvertex = true;
8577 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8578 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8581 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8582 break; // if wavefunc is a nop, ignore this transform
8583 dynamicvertex = true;
8584 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8585 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8589 switch(rsurface.texture->tcgen.tcgen)
8592 case Q3TCGEN_TEXTURE:
8594 case Q3TCGEN_LIGHTMAP:
8595 dynamicvertex = true;
8596 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8597 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8599 case Q3TCGEN_VECTOR:
8600 dynamicvertex = true;
8601 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8602 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8604 case Q3TCGEN_ENVIRONMENT:
8605 dynamicvertex = true;
8606 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8607 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8610 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8612 dynamicvertex = true;
8613 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8614 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8617 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8619 dynamicvertex = true;
8620 batchneed |= BATCHNEED_NOGAPS;
8621 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8624 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8626 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8627 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8628 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8629 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8630 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8631 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8632 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8635 // when the model data has no vertex buffer (dynamic mesh), we need to
8637 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8638 batchneed |= BATCHNEED_NOGAPS;
8640 // if needsupdate, we have to do a dynamic vertex batch for sure
8641 if (needsupdate & batchneed)
8642 dynamicvertex = true;
8644 // see if we need to build vertexmesh from arrays
8645 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8646 dynamicvertex = true;
8648 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8649 // also some drivers strongly dislike firstvertex
8650 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8651 dynamicvertex = true;
8653 rsurface.batchvertex3f = rsurface.modelvertex3f;
8654 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8655 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8656 rsurface.batchsvector3f = rsurface.modelsvector3f;
8657 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8658 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8659 rsurface.batchtvector3f = rsurface.modeltvector3f;
8660 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8661 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8662 rsurface.batchnormal3f = rsurface.modelnormal3f;
8663 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8664 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8665 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8666 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8667 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8668 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8669 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8670 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8671 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8672 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8673 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8674 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8675 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8676 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8677 rsurface.batchelement3i = rsurface.modelelement3i;
8678 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8679 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8680 rsurface.batchelement3s = rsurface.modelelement3s;
8681 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8682 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8684 // if any dynamic vertex processing has to occur in software, we copy the
8685 // entire surface list together before processing to rebase the vertices
8686 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8688 // if any gaps exist and we do not have a static vertex buffer, we have to
8689 // copy the surface list together to avoid wasting upload bandwidth on the
8690 // vertices in the gaps.
8692 // if gaps exist and we have a static vertex buffer, we still have to
8693 // combine the index buffer ranges into one dynamic index buffer.
8695 // in all cases we end up with data that can be drawn in one call.
8699 // static vertex data, just set pointers...
8700 rsurface.batchgeneratedvertex = false;
8701 // if there are gaps, we want to build a combined index buffer,
8702 // otherwise use the original static buffer with an appropriate offset
8705 // build a new triangle elements array for this batch
8706 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8707 rsurface.batchfirsttriangle = 0;
8709 for (i = 0;i < texturenumsurfaces;i++)
8711 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8712 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8713 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8714 numtriangles += surfacenumtriangles;
8716 rsurface.batchelement3i_indexbuffer = NULL;
8717 rsurface.batchelement3i_bufferoffset = 0;
8718 rsurface.batchelement3s = NULL;
8719 rsurface.batchelement3s_indexbuffer = NULL;
8720 rsurface.batchelement3s_bufferoffset = 0;
8721 if (endvertex <= 65536)
8723 // make a 16bit (unsigned short) index array if possible
8724 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8725 for (i = 0;i < numtriangles*3;i++)
8726 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8732 // something needs software processing, do it for real...
8733 // we only directly handle separate array data in this case and then
8734 // generate interleaved data if needed...
8735 rsurface.batchgeneratedvertex = true;
8737 // now copy the vertex data into a combined array and make an index array
8738 // (this is what Quake3 does all the time)
8739 //if (gaps || rsurface.batchfirstvertex)
8741 rsurface.batchvertex3fbuffer = NULL;
8742 rsurface.batchvertexmesh = NULL;
8743 rsurface.batchvertexmeshbuffer = NULL;
8744 rsurface.batchvertex3f = NULL;
8745 rsurface.batchvertex3f_vertexbuffer = NULL;
8746 rsurface.batchvertex3f_bufferoffset = 0;
8747 rsurface.batchsvector3f = NULL;
8748 rsurface.batchsvector3f_vertexbuffer = NULL;
8749 rsurface.batchsvector3f_bufferoffset = 0;
8750 rsurface.batchtvector3f = NULL;
8751 rsurface.batchtvector3f_vertexbuffer = NULL;
8752 rsurface.batchtvector3f_bufferoffset = 0;
8753 rsurface.batchnormal3f = NULL;
8754 rsurface.batchnormal3f_vertexbuffer = NULL;
8755 rsurface.batchnormal3f_bufferoffset = 0;
8756 rsurface.batchlightmapcolor4f = NULL;
8757 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8758 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8759 rsurface.batchtexcoordtexture2f = NULL;
8760 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8761 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8762 rsurface.batchtexcoordlightmap2f = NULL;
8763 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8764 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8765 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8766 rsurface.batchelement3i_indexbuffer = NULL;
8767 rsurface.batchelement3i_bufferoffset = 0;
8768 rsurface.batchelement3s = NULL;
8769 rsurface.batchelement3s_indexbuffer = NULL;
8770 rsurface.batchelement3s_bufferoffset = 0;
8771 // we'll only be setting up certain arrays as needed
8772 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8773 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8774 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8775 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8776 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8777 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8778 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8780 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8781 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8783 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8784 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8785 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8786 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8787 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8788 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8791 for (i = 0;i < texturenumsurfaces;i++)
8793 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8794 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8795 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8796 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8797 // copy only the data requested
8798 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8799 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8800 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8802 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8804 if (rsurface.batchvertex3f)
8805 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8807 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8809 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8811 if (rsurface.modelnormal3f)
8812 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8814 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8816 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8818 if (rsurface.modelsvector3f)
8820 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8821 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8825 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8826 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8829 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8831 if (rsurface.modellightmapcolor4f)
8832 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8834 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8836 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8838 if (rsurface.modeltexcoordtexture2f)
8839 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8841 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8843 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8845 if (rsurface.modeltexcoordlightmap2f)
8846 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8848 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8851 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8852 numvertices += surfacenumvertices;
8853 numtriangles += surfacenumtriangles;
8856 // generate a 16bit index array as well if possible
8857 // (in general, dynamic batches fit)
8858 if (numvertices <= 65536)
8860 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8861 for (i = 0;i < numtriangles*3;i++)
8862 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8865 // since we've copied everything, the batch now starts at 0
8866 rsurface.batchfirstvertex = 0;
8867 rsurface.batchnumvertices = batchnumvertices;
8868 rsurface.batchfirsttriangle = 0;
8869 rsurface.batchnumtriangles = batchnumtriangles;
8872 // q1bsp surfaces rendered in vertex color mode have to have colors
8873 // calculated based on lightstyles
8874 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8876 // generate color arrays for the surfaces in this list
8881 const unsigned char *lm;
8882 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8883 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8884 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8886 for (i = 0;i < texturenumsurfaces;i++)
8888 surface = texturesurfacelist[i];
8889 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8890 surfacenumvertices = surface->num_vertices;
8891 if (surface->lightmapinfo->samples)
8893 for (j = 0;j < surfacenumvertices;j++)
8895 lm = surface->lightmapinfo->samples + offsets[j];
8896 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8897 VectorScale(lm, scale, c);
8898 if (surface->lightmapinfo->styles[1] != 255)
8900 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8902 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8903 VectorMA(c, scale, lm, c);
8904 if (surface->lightmapinfo->styles[2] != 255)
8907 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8908 VectorMA(c, scale, lm, c);
8909 if (surface->lightmapinfo->styles[3] != 255)
8912 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8913 VectorMA(c, scale, lm, c);
8920 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);
8926 for (j = 0;j < surfacenumvertices;j++)
8928 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8935 // if vertices are deformed (sprite flares and things in maps, possibly
8936 // water waves, bulges and other deformations), modify the copied vertices
8938 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8940 switch (deform->deform)
8943 case Q3DEFORM_PROJECTIONSHADOW:
8944 case Q3DEFORM_TEXT0:
8945 case Q3DEFORM_TEXT1:
8946 case Q3DEFORM_TEXT2:
8947 case Q3DEFORM_TEXT3:
8948 case Q3DEFORM_TEXT4:
8949 case Q3DEFORM_TEXT5:
8950 case Q3DEFORM_TEXT6:
8951 case Q3DEFORM_TEXT7:
8954 case Q3DEFORM_AUTOSPRITE:
8955 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8956 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8957 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8958 VectorNormalize(newforward);
8959 VectorNormalize(newright);
8960 VectorNormalize(newup);
8961 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8962 // rsurface.batchvertex3f_vertexbuffer = NULL;
8963 // rsurface.batchvertex3f_bufferoffset = 0;
8964 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8965 // rsurface.batchsvector3f_vertexbuffer = NULL;
8966 // rsurface.batchsvector3f_bufferoffset = 0;
8967 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8968 // rsurface.batchtvector3f_vertexbuffer = NULL;
8969 // rsurface.batchtvector3f_bufferoffset = 0;
8970 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8971 // rsurface.batchnormal3f_vertexbuffer = NULL;
8972 // rsurface.batchnormal3f_bufferoffset = 0;
8973 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8974 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8975 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8976 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8977 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);
8978 // a single autosprite surface can contain multiple sprites...
8979 for (j = 0;j < batchnumvertices - 3;j += 4)
8981 VectorClear(center);
8982 for (i = 0;i < 4;i++)
8983 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8984 VectorScale(center, 0.25f, center);
8985 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8986 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8987 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8988 for (i = 0;i < 4;i++)
8990 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8991 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8994 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8995 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8996 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);
8998 case Q3DEFORM_AUTOSPRITE2:
8999 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9000 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9001 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9002 VectorNormalize(newforward);
9003 VectorNormalize(newright);
9004 VectorNormalize(newup);
9005 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9006 // rsurface.batchvertex3f_vertexbuffer = NULL;
9007 // rsurface.batchvertex3f_bufferoffset = 0;
9009 const float *v1, *v2;
9019 memset(shortest, 0, sizeof(shortest));
9020 // a single autosprite surface can contain multiple sprites...
9021 for (j = 0;j < batchnumvertices - 3;j += 4)
9023 VectorClear(center);
9024 for (i = 0;i < 4;i++)
9025 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9026 VectorScale(center, 0.25f, center);
9027 // find the two shortest edges, then use them to define the
9028 // axis vectors for rotating around the central axis
9029 for (i = 0;i < 6;i++)
9031 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9032 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9033 l = VectorDistance2(v1, v2);
9034 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9036 l += (1.0f / 1024.0f);
9037 if (shortest[0].length2 > l || i == 0)
9039 shortest[1] = shortest[0];
9040 shortest[0].length2 = l;
9041 shortest[0].v1 = v1;
9042 shortest[0].v2 = v2;
9044 else if (shortest[1].length2 > l || i == 1)
9046 shortest[1].length2 = l;
9047 shortest[1].v1 = v1;
9048 shortest[1].v2 = v2;
9051 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9052 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9053 // this calculates the right vector from the shortest edge
9054 // and the up vector from the edge midpoints
9055 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9056 VectorNormalize(right);
9057 VectorSubtract(end, start, up);
9058 VectorNormalize(up);
9059 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9060 VectorSubtract(rsurface.localvieworigin, center, forward);
9061 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9062 VectorNegate(forward, forward);
9063 VectorReflect(forward, 0, up, forward);
9064 VectorNormalize(forward);
9065 CrossProduct(up, forward, newright);
9066 VectorNormalize(newright);
9067 // rotate the quad around the up axis vector, this is made
9068 // especially easy by the fact we know the quad is flat,
9069 // so we only have to subtract the center position and
9070 // measure distance along the right vector, and then
9071 // multiply that by the newright vector and add back the
9073 // we also need to subtract the old position to undo the
9074 // displacement from the center, which we do with a
9075 // DotProduct, the subtraction/addition of center is also
9076 // optimized into DotProducts here
9077 l = DotProduct(right, center);
9078 for (i = 0;i < 4;i++)
9080 v1 = rsurface.batchvertex3f + 3*(j+i);
9081 f = DotProduct(right, v1) - l;
9082 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9086 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9088 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9089 // rsurface.batchnormal3f_vertexbuffer = NULL;
9090 // rsurface.batchnormal3f_bufferoffset = 0;
9091 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9093 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9095 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9096 // rsurface.batchsvector3f_vertexbuffer = NULL;
9097 // rsurface.batchsvector3f_bufferoffset = 0;
9098 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9099 // rsurface.batchtvector3f_vertexbuffer = NULL;
9100 // rsurface.batchtvector3f_bufferoffset = 0;
9101 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);
9104 case Q3DEFORM_NORMAL:
9105 // deform the normals to make reflections wavey
9106 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9107 rsurface.batchnormal3f_vertexbuffer = NULL;
9108 rsurface.batchnormal3f_bufferoffset = 0;
9109 for (j = 0;j < batchnumvertices;j++)
9112 float *normal = rsurface.batchnormal3f + 3*j;
9113 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9114 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9115 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9116 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9117 VectorNormalize(normal);
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);
9131 // deform vertex array to make wavey water and flags and such
9132 waveparms[0] = deform->waveparms[0];
9133 waveparms[1] = deform->waveparms[1];
9134 waveparms[2] = deform->waveparms[2];
9135 waveparms[3] = deform->waveparms[3];
9136 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9137 break; // if wavefunc is a nop, don't make a dynamic vertex array
9138 // this is how a divisor of vertex influence on deformation
9139 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9140 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9141 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9142 // rsurface.batchvertex3f_vertexbuffer = NULL;
9143 // rsurface.batchvertex3f_bufferoffset = 0;
9144 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9145 // rsurface.batchnormal3f_vertexbuffer = NULL;
9146 // rsurface.batchnormal3f_bufferoffset = 0;
9147 for (j = 0;j < batchnumvertices;j++)
9149 // if the wavefunc depends on time, evaluate it per-vertex
9152 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9153 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9155 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9157 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9158 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9159 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9161 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9162 // rsurface.batchsvector3f_vertexbuffer = NULL;
9163 // rsurface.batchsvector3f_bufferoffset = 0;
9164 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9165 // rsurface.batchtvector3f_vertexbuffer = NULL;
9166 // rsurface.batchtvector3f_bufferoffset = 0;
9167 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);
9170 case Q3DEFORM_BULGE:
9171 // deform vertex array to make the surface have moving bulges
9172 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9173 // rsurface.batchvertex3f_vertexbuffer = NULL;
9174 // rsurface.batchvertex3f_bufferoffset = 0;
9175 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9176 // rsurface.batchnormal3f_vertexbuffer = NULL;
9177 // rsurface.batchnormal3f_bufferoffset = 0;
9178 for (j = 0;j < batchnumvertices;j++)
9180 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
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);
9197 // deform vertex array
9198 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9199 break; // if wavefunc is a nop, don't make a dynamic vertex array
9200 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9201 VectorScale(deform->parms, scale, waveparms);
9202 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9203 // rsurface.batchvertex3f_vertexbuffer = NULL;
9204 // rsurface.batchvertex3f_bufferoffset = 0;
9205 for (j = 0;j < batchnumvertices;j++)
9206 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9211 // generate texcoords based on the chosen texcoord source
9212 switch(rsurface.texture->tcgen.tcgen)
9215 case Q3TCGEN_TEXTURE:
9217 case Q3TCGEN_LIGHTMAP:
9218 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9219 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9220 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9221 if (rsurface.batchtexcoordlightmap2f)
9222 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9224 case Q3TCGEN_VECTOR:
9225 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9226 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9227 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9228 for (j = 0;j < batchnumvertices;j++)
9230 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9231 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9234 case Q3TCGEN_ENVIRONMENT:
9235 // make environment reflections using a spheremap
9236 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9237 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9238 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9239 for (j = 0;j < batchnumvertices;j++)
9241 // identical to Q3A's method, but executed in worldspace so
9242 // carried models can be shiny too
9244 float viewer[3], d, reflected[3], worldreflected[3];
9246 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9247 // VectorNormalize(viewer);
9249 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9251 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9252 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9253 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9254 // note: this is proportinal to viewer, so we can normalize later
9256 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9257 VectorNormalize(worldreflected);
9259 // note: this sphere map only uses world x and z!
9260 // so positive and negative y will LOOK THE SAME.
9261 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9262 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9266 // the only tcmod that needs software vertex processing is turbulent, so
9267 // check for it here and apply the changes if needed
9268 // and we only support that as the first one
9269 // (handling a mixture of turbulent and other tcmods would be problematic
9270 // without punting it entirely to a software path)
9271 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9273 amplitude = rsurface.texture->tcmods[0].parms[1];
9274 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9275 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9276 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9277 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9278 for (j = 0;j < batchnumvertices;j++)
9280 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);
9281 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9285 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9287 // convert the modified arrays to vertex structs
9288 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9289 // rsurface.batchvertexmeshbuffer = NULL;
9290 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9291 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9292 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9293 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9294 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9295 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9296 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9298 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9300 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9301 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9304 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9305 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9306 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9307 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9308 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9309 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9310 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9311 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9312 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9316 void RSurf_DrawBatch(void)
9318 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9319 // through the pipeline, killing it earlier in the pipeline would have
9320 // per-surface overhead rather than per-batch overhead, so it's best to
9321 // reject it here, before it hits glDraw.
9322 if (rsurface.batchnumtriangles == 0)
9325 // batch debugging code
9326 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9332 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9333 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9336 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9338 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9340 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9341 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);
9348 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);
9351 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9353 // pick the closest matching water plane
9354 int planeindex, vertexindex, bestplaneindex = -1;
9358 r_waterstate_waterplane_t *p;
9359 qboolean prepared = false;
9361 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9363 if(p->camera_entity != rsurface.texture->camera_entity)
9368 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9370 if(rsurface.batchnumvertices == 0)
9373 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9375 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9376 d += fabs(PlaneDiff(vert, &p->plane));
9378 if (bestd > d || bestplaneindex < 0)
9381 bestplaneindex = planeindex;
9384 return bestplaneindex;
9385 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9386 // this situation though, as it might be better to render single larger
9387 // batches with useless stuff (backface culled for example) than to
9388 // render multiple smaller batches
9391 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9394 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9395 rsurface.passcolor4f_vertexbuffer = 0;
9396 rsurface.passcolor4f_bufferoffset = 0;
9397 for (i = 0;i < rsurface.batchnumvertices;i++)
9398 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9401 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9408 if (rsurface.passcolor4f)
9410 // generate color arrays
9411 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9412 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9413 rsurface.passcolor4f_vertexbuffer = 0;
9414 rsurface.passcolor4f_bufferoffset = 0;
9415 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)
9417 f = RSurf_FogVertex(v);
9426 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9427 rsurface.passcolor4f_vertexbuffer = 0;
9428 rsurface.passcolor4f_bufferoffset = 0;
9429 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9431 f = RSurf_FogVertex(v);
9440 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9447 if (!rsurface.passcolor4f)
9449 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9450 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9451 rsurface.passcolor4f_vertexbuffer = 0;
9452 rsurface.passcolor4f_bufferoffset = 0;
9453 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)
9455 f = RSurf_FogVertex(v);
9456 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9457 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9458 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9463 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9468 if (!rsurface.passcolor4f)
9470 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9471 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9472 rsurface.passcolor4f_vertexbuffer = 0;
9473 rsurface.passcolor4f_bufferoffset = 0;
9474 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9483 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9488 if (!rsurface.passcolor4f)
9490 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9491 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9492 rsurface.passcolor4f_vertexbuffer = 0;
9493 rsurface.passcolor4f_bufferoffset = 0;
9494 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9496 c2[0] = c[0] + r_refdef.scene.ambient;
9497 c2[1] = c[1] + r_refdef.scene.ambient;
9498 c2[2] = c[2] + r_refdef.scene.ambient;
9503 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9506 rsurface.passcolor4f = NULL;
9507 rsurface.passcolor4f_vertexbuffer = 0;
9508 rsurface.passcolor4f_bufferoffset = 0;
9509 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9510 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9511 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9512 GL_Color(r, g, b, a);
9513 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9517 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9519 // TODO: optimize applyfog && applycolor case
9520 // just apply fog if necessary, and tint the fog color array if necessary
9521 rsurface.passcolor4f = NULL;
9522 rsurface.passcolor4f_vertexbuffer = 0;
9523 rsurface.passcolor4f_bufferoffset = 0;
9524 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9525 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9526 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9527 GL_Color(r, g, b, a);
9531 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9534 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9535 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9536 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9537 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9538 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9539 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9540 GL_Color(r, g, b, a);
9544 static void RSurf_DrawBatch_GL11_ClampColor(void)
9549 if (!rsurface.passcolor4f)
9551 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9553 c2[0] = bound(0.0f, c1[0], 1.0f);
9554 c2[1] = bound(0.0f, c1[1], 1.0f);
9555 c2[2] = bound(0.0f, c1[2], 1.0f);
9556 c2[3] = bound(0.0f, c1[3], 1.0f);
9560 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9570 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9571 rsurface.passcolor4f_vertexbuffer = 0;
9572 rsurface.passcolor4f_bufferoffset = 0;
9573 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)
9575 f = -DotProduct(r_refdef.view.forward, n);
9577 f = f * 0.85 + 0.15; // work around so stuff won't get black
9578 f *= r_refdef.lightmapintensity;
9579 Vector4Set(c, f, f, f, 1);
9583 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9585 RSurf_DrawBatch_GL11_ApplyFakeLight();
9586 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9587 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9588 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9589 GL_Color(r, g, b, a);
9593 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9601 vec3_t ambientcolor;
9602 vec3_t diffusecolor;
9606 VectorCopy(rsurface.modellight_lightdir, lightdir);
9607 f = 0.5f * r_refdef.lightmapintensity;
9608 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9609 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9610 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9611 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9612 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9613 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9615 if (VectorLength2(diffusecolor) > 0)
9617 // q3-style directional shading
9618 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9619 rsurface.passcolor4f_vertexbuffer = 0;
9620 rsurface.passcolor4f_bufferoffset = 0;
9621 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)
9623 if ((f = DotProduct(n, lightdir)) > 0)
9624 VectorMA(ambientcolor, f, diffusecolor, c);
9626 VectorCopy(ambientcolor, c);
9633 *applycolor = false;
9637 *r = ambientcolor[0];
9638 *g = ambientcolor[1];
9639 *b = ambientcolor[2];
9640 rsurface.passcolor4f = NULL;
9641 rsurface.passcolor4f_vertexbuffer = 0;
9642 rsurface.passcolor4f_bufferoffset = 0;
9646 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9648 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9649 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9650 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9651 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9652 GL_Color(r, g, b, a);
9656 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9664 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9665 rsurface.passcolor4f_vertexbuffer = 0;
9666 rsurface.passcolor4f_bufferoffset = 0;
9668 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9670 f = 1 - RSurf_FogVertex(v);
9678 void RSurf_SetupDepthAndCulling(void)
9680 // submodels are biased to avoid z-fighting with world surfaces that they
9681 // may be exactly overlapping (avoids z-fighting artifacts on certain
9682 // doors and things in Quake maps)
9683 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9684 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9685 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9686 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9689 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9691 // transparent sky would be ridiculous
9692 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9694 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9695 skyrenderlater = true;
9696 RSurf_SetupDepthAndCulling();
9698 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9699 // skymasking on them, and Quake3 never did sky masking (unlike
9700 // software Quake and software Quake2), so disable the sky masking
9701 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9702 // and skymasking also looks very bad when noclipping outside the
9703 // level, so don't use it then either.
9704 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9706 R_Mesh_ResetTextureState();
9707 if (skyrendermasked)
9709 R_SetupShader_DepthOrShadow(false);
9710 // depth-only (masking)
9711 GL_ColorMask(0,0,0,0);
9712 // just to make sure that braindead drivers don't draw
9713 // anything despite that colormask...
9714 GL_BlendFunc(GL_ZERO, GL_ONE);
9715 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9716 if (rsurface.batchvertex3fbuffer)
9717 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9719 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9723 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9725 GL_BlendFunc(GL_ONE, GL_ZERO);
9726 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9727 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9728 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9731 if (skyrendermasked)
9732 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9734 R_Mesh_ResetTextureState();
9735 GL_Color(1, 1, 1, 1);
9738 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9739 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9740 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9742 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9746 // render screenspace normalmap to texture
9748 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9752 // bind lightmap texture
9754 // water/refraction/reflection/camera surfaces have to be handled specially
9755 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9757 int start, end, startplaneindex;
9758 for (start = 0;start < texturenumsurfaces;start = end)
9760 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9761 if(startplaneindex < 0)
9763 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9764 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9768 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9770 // now that we have a batch using the same planeindex, render it
9771 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9773 // render water or distortion background
9775 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);
9777 // blend surface on top
9778 GL_DepthMask(false);
9779 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9782 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9784 // render surface with reflection texture as input
9785 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9786 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);
9793 // render surface batch normally
9794 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9795 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);
9799 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9801 // OpenGL 1.3 path - anything not completely ancient
9802 qboolean applycolor;
9805 const texturelayer_t *layer;
9806 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);
9807 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9809 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9812 int layertexrgbscale;
9813 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9815 if (layerindex == 0)
9819 GL_AlphaTest(false);
9820 GL_DepthFunc(GL_EQUAL);
9823 GL_DepthMask(layer->depthmask && writedepth);
9824 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9825 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9827 layertexrgbscale = 4;
9828 VectorScale(layer->color, 0.25f, layercolor);
9830 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9832 layertexrgbscale = 2;
9833 VectorScale(layer->color, 0.5f, layercolor);
9837 layertexrgbscale = 1;
9838 VectorScale(layer->color, 1.0f, layercolor);
9840 layercolor[3] = layer->color[3];
9841 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9842 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9843 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9844 switch (layer->type)
9846 case TEXTURELAYERTYPE_LITTEXTURE:
9847 // single-pass lightmapped texture with 2x rgbscale
9848 R_Mesh_TexBind(0, r_texture_white);
9849 R_Mesh_TexMatrix(0, NULL);
9850 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9851 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9852 R_Mesh_TexBind(1, layer->texture);
9853 R_Mesh_TexMatrix(1, &layer->texmatrix);
9854 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9855 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9856 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9857 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9858 else if (FAKELIGHT_ENABLED)
9859 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9860 else if (rsurface.uselightmaptexture)
9861 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9863 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9865 case TEXTURELAYERTYPE_TEXTURE:
9866 // singletexture unlit texture with transparency support
9867 R_Mesh_TexBind(0, layer->texture);
9868 R_Mesh_TexMatrix(0, &layer->texmatrix);
9869 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9870 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9871 R_Mesh_TexBind(1, 0);
9872 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9873 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9875 case TEXTURELAYERTYPE_FOG:
9876 // singletexture fogging
9879 R_Mesh_TexBind(0, layer->texture);
9880 R_Mesh_TexMatrix(0, &layer->texmatrix);
9881 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9882 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9886 R_Mesh_TexBind(0, 0);
9887 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9889 R_Mesh_TexBind(1, 0);
9890 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9891 // generate a color array for the fog pass
9892 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9893 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9897 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9900 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9902 GL_DepthFunc(GL_LEQUAL);
9903 GL_AlphaTest(false);
9907 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9909 // OpenGL 1.1 - crusty old voodoo path
9912 const texturelayer_t *layer;
9913 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);
9914 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9916 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9918 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9920 if (layerindex == 0)
9924 GL_AlphaTest(false);
9925 GL_DepthFunc(GL_EQUAL);
9928 GL_DepthMask(layer->depthmask && writedepth);
9929 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9930 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9931 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9932 switch (layer->type)
9934 case TEXTURELAYERTYPE_LITTEXTURE:
9935 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9937 // two-pass lit texture with 2x rgbscale
9938 // first the lightmap pass
9939 R_Mesh_TexBind(0, r_texture_white);
9940 R_Mesh_TexMatrix(0, NULL);
9941 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9942 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9943 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9944 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9945 else if (FAKELIGHT_ENABLED)
9946 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9947 else if (rsurface.uselightmaptexture)
9948 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9950 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9951 // then apply the texture to it
9952 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9953 R_Mesh_TexBind(0, layer->texture);
9954 R_Mesh_TexMatrix(0, &layer->texmatrix);
9955 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9956 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9957 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);
9961 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9962 R_Mesh_TexBind(0, layer->texture);
9963 R_Mesh_TexMatrix(0, &layer->texmatrix);
9964 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9965 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9966 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9967 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);
9969 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);
9972 case TEXTURELAYERTYPE_TEXTURE:
9973 // singletexture unlit texture with transparency support
9974 R_Mesh_TexBind(0, layer->texture);
9975 R_Mesh_TexMatrix(0, &layer->texmatrix);
9976 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9977 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9978 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);
9980 case TEXTURELAYERTYPE_FOG:
9981 // singletexture fogging
9984 R_Mesh_TexBind(0, layer->texture);
9985 R_Mesh_TexMatrix(0, &layer->texmatrix);
9986 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9987 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9991 R_Mesh_TexBind(0, 0);
9992 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9994 // generate a color array for the fog pass
9995 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9996 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10000 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10003 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10005 GL_DepthFunc(GL_LEQUAL);
10006 GL_AlphaTest(false);
10010 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10014 r_vertexgeneric_t *batchvertex;
10017 // R_Mesh_ResetTextureState();
10018 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10020 if(rsurface.texture && rsurface.texture->currentskinframe)
10022 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10023 c[3] *= rsurface.texture->currentalpha;
10033 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10035 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10036 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10037 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10040 // brighten it up (as texture value 127 means "unlit")
10041 c[0] *= 2 * r_refdef.view.colorscale;
10042 c[1] *= 2 * r_refdef.view.colorscale;
10043 c[2] *= 2 * r_refdef.view.colorscale;
10045 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10046 c[3] *= r_wateralpha.value;
10048 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10050 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10051 GL_DepthMask(false);
10053 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10055 GL_BlendFunc(GL_ONE, GL_ONE);
10056 GL_DepthMask(false);
10058 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10060 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10061 GL_DepthMask(false);
10063 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10065 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10066 GL_DepthMask(false);
10070 GL_BlendFunc(GL_ONE, GL_ZERO);
10071 GL_DepthMask(writedepth);
10074 if (r_showsurfaces.integer == 3)
10076 rsurface.passcolor4f = NULL;
10078 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10080 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10082 rsurface.passcolor4f = NULL;
10083 rsurface.passcolor4f_vertexbuffer = 0;
10084 rsurface.passcolor4f_bufferoffset = 0;
10086 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10088 qboolean applycolor = true;
10091 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10093 r_refdef.lightmapintensity = 1;
10094 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10095 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10097 else if (FAKELIGHT_ENABLED)
10099 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10101 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10102 RSurf_DrawBatch_GL11_ApplyFakeLight();
10103 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10107 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10109 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10110 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10111 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10114 if(!rsurface.passcolor4f)
10115 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10117 RSurf_DrawBatch_GL11_ApplyAmbient();
10118 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10119 if(r_refdef.fogenabled)
10120 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10121 RSurf_DrawBatch_GL11_ClampColor();
10123 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10124 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10127 else if (!r_refdef.view.showdebug)
10129 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10130 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10131 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10133 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10134 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10136 R_Mesh_PrepareVertices_Generic_Unlock();
10139 else if (r_showsurfaces.integer == 4)
10141 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10142 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10143 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10145 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10146 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10147 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10149 R_Mesh_PrepareVertices_Generic_Unlock();
10152 else if (r_showsurfaces.integer == 2)
10155 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10156 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10157 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10159 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10160 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10161 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10162 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10163 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10164 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10165 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10167 R_Mesh_PrepareVertices_Generic_Unlock();
10168 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10172 int texturesurfaceindex;
10174 const msurface_t *surface;
10175 float surfacecolor4f[4];
10176 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10177 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10179 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10181 surface = texturesurfacelist[texturesurfaceindex];
10182 k = (int)(((size_t)surface) / sizeof(msurface_t));
10183 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10184 for (j = 0;j < surface->num_vertices;j++)
10186 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10187 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10191 R_Mesh_PrepareVertices_Generic_Unlock();
10196 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10199 RSurf_SetupDepthAndCulling();
10200 if (r_showsurfaces.integer)
10202 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10205 switch (vid.renderpath)
10207 case RENDERPATH_GL20:
10208 case RENDERPATH_D3D9:
10209 case RENDERPATH_D3D10:
10210 case RENDERPATH_D3D11:
10211 case RENDERPATH_SOFT:
10212 case RENDERPATH_GLES2:
10213 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10215 case RENDERPATH_GL13:
10216 case RENDERPATH_GLES1:
10217 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10219 case RENDERPATH_GL11:
10220 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10226 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10229 RSurf_SetupDepthAndCulling();
10230 if (r_showsurfaces.integer)
10232 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10235 switch (vid.renderpath)
10237 case RENDERPATH_GL20:
10238 case RENDERPATH_D3D9:
10239 case RENDERPATH_D3D10:
10240 case RENDERPATH_D3D11:
10241 case RENDERPATH_SOFT:
10242 case RENDERPATH_GLES2:
10243 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10245 case RENDERPATH_GL13:
10246 case RENDERPATH_GLES1:
10247 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10249 case RENDERPATH_GL11:
10250 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10256 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10259 int texturenumsurfaces, endsurface;
10260 texture_t *texture;
10261 const msurface_t *surface;
10262 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10264 // if the model is static it doesn't matter what value we give for
10265 // wantnormals and wanttangents, so this logic uses only rules applicable
10266 // to a model, knowing that they are meaningless otherwise
10267 if (ent == r_refdef.scene.worldentity)
10268 RSurf_ActiveWorldEntity();
10269 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10270 RSurf_ActiveModelEntity(ent, false, false, false);
10273 switch (vid.renderpath)
10275 case RENDERPATH_GL20:
10276 case RENDERPATH_D3D9:
10277 case RENDERPATH_D3D10:
10278 case RENDERPATH_D3D11:
10279 case RENDERPATH_SOFT:
10280 case RENDERPATH_GLES2:
10281 RSurf_ActiveModelEntity(ent, true, true, false);
10283 case RENDERPATH_GL11:
10284 case RENDERPATH_GL13:
10285 case RENDERPATH_GLES1:
10286 RSurf_ActiveModelEntity(ent, true, false, false);
10291 if (r_transparentdepthmasking.integer)
10293 qboolean setup = false;
10294 for (i = 0;i < numsurfaces;i = j)
10297 surface = rsurface.modelsurfaces + surfacelist[i];
10298 texture = surface->texture;
10299 rsurface.texture = R_GetCurrentTexture(texture);
10300 rsurface.lightmaptexture = NULL;
10301 rsurface.deluxemaptexture = NULL;
10302 rsurface.uselightmaptexture = false;
10303 // scan ahead until we find a different texture
10304 endsurface = min(i + 1024, numsurfaces);
10305 texturenumsurfaces = 0;
10306 texturesurfacelist[texturenumsurfaces++] = surface;
10307 for (;j < endsurface;j++)
10309 surface = rsurface.modelsurfaces + surfacelist[j];
10310 if (texture != surface->texture)
10312 texturesurfacelist[texturenumsurfaces++] = surface;
10314 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10316 // render the range of surfaces as depth
10320 GL_ColorMask(0,0,0,0);
10322 GL_DepthTest(true);
10323 GL_BlendFunc(GL_ONE, GL_ZERO);
10324 GL_DepthMask(true);
10325 // R_Mesh_ResetTextureState();
10326 R_SetupShader_DepthOrShadow(false);
10328 RSurf_SetupDepthAndCulling();
10329 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10330 if (rsurface.batchvertex3fbuffer)
10331 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10333 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10337 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10340 for (i = 0;i < numsurfaces;i = j)
10343 surface = rsurface.modelsurfaces + surfacelist[i];
10344 texture = surface->texture;
10345 rsurface.texture = R_GetCurrentTexture(texture);
10346 // scan ahead until we find a different texture
10347 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10348 texturenumsurfaces = 0;
10349 texturesurfacelist[texturenumsurfaces++] = surface;
10350 if(FAKELIGHT_ENABLED)
10352 rsurface.lightmaptexture = NULL;
10353 rsurface.deluxemaptexture = NULL;
10354 rsurface.uselightmaptexture = false;
10355 for (;j < endsurface;j++)
10357 surface = rsurface.modelsurfaces + surfacelist[j];
10358 if (texture != surface->texture)
10360 texturesurfacelist[texturenumsurfaces++] = surface;
10365 rsurface.lightmaptexture = surface->lightmaptexture;
10366 rsurface.deluxemaptexture = surface->deluxemaptexture;
10367 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10368 for (;j < endsurface;j++)
10370 surface = rsurface.modelsurfaces + surfacelist[j];
10371 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10373 texturesurfacelist[texturenumsurfaces++] = surface;
10376 // render the range of surfaces
10377 if (ent == r_refdef.scene.worldentity)
10378 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10380 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10382 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10385 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10387 // transparent surfaces get pushed off into the transparent queue
10388 int surfacelistindex;
10389 const msurface_t *surface;
10390 vec3_t tempcenter, center;
10391 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10393 surface = texturesurfacelist[surfacelistindex];
10394 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10395 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10396 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10397 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10398 if (queueentity->transparent_offset) // transparent offset
10400 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10401 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10402 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10404 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10408 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10410 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10412 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10414 RSurf_SetupDepthAndCulling();
10415 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10416 if (rsurface.batchvertex3fbuffer)
10417 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10419 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10423 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10425 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10428 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10431 if (!rsurface.texture->currentnumlayers)
10433 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10434 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10436 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10438 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10439 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10440 else if (!rsurface.texture->currentnumlayers)
10442 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10444 // in the deferred case, transparent surfaces were queued during prepass
10445 if (!r_shadow_usingdeferredprepass)
10446 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10450 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10451 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10456 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10459 texture_t *texture;
10460 R_FrameData_SetMark();
10461 // break the surface list down into batches by texture and use of lightmapping
10462 for (i = 0;i < numsurfaces;i = j)
10465 // texture is the base texture pointer, rsurface.texture is the
10466 // current frame/skin the texture is directing us to use (for example
10467 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10468 // use skin 1 instead)
10469 texture = surfacelist[i]->texture;
10470 rsurface.texture = R_GetCurrentTexture(texture);
10471 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10473 // if this texture is not the kind we want, skip ahead to the next one
10474 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10478 if(FAKELIGHT_ENABLED || depthonly || prepass)
10480 rsurface.lightmaptexture = NULL;
10481 rsurface.deluxemaptexture = NULL;
10482 rsurface.uselightmaptexture = false;
10483 // simply scan ahead until we find a different texture or lightmap state
10484 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10489 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10490 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10491 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10492 // simply scan ahead until we find a different texture or lightmap state
10493 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10496 // render the range of surfaces
10497 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10499 R_FrameData_ReturnToMark();
10502 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10506 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10509 if (!rsurface.texture->currentnumlayers)
10511 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10512 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10514 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10516 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10517 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10518 else if (!rsurface.texture->currentnumlayers)
10520 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10522 // in the deferred case, transparent surfaces were queued during prepass
10523 if (!r_shadow_usingdeferredprepass)
10524 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10528 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10529 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10534 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10537 texture_t *texture;
10538 R_FrameData_SetMark();
10539 // break the surface list down into batches by texture and use of lightmapping
10540 for (i = 0;i < numsurfaces;i = j)
10543 // texture is the base texture pointer, rsurface.texture is the
10544 // current frame/skin the texture is directing us to use (for example
10545 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10546 // use skin 1 instead)
10547 texture = surfacelist[i]->texture;
10548 rsurface.texture = R_GetCurrentTexture(texture);
10549 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10551 // if this texture is not the kind we want, skip ahead to the next one
10552 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10556 if(FAKELIGHT_ENABLED || depthonly || prepass)
10558 rsurface.lightmaptexture = NULL;
10559 rsurface.deluxemaptexture = NULL;
10560 rsurface.uselightmaptexture = false;
10561 // simply scan ahead until we find a different texture or lightmap state
10562 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10567 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10568 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10569 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10570 // simply scan ahead until we find a different texture or lightmap state
10571 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10574 // render the range of surfaces
10575 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10577 R_FrameData_ReturnToMark();
10580 float locboxvertex3f[6*4*3] =
10582 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10583 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10584 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10585 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10586 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10587 1,0,0, 0,0,0, 0,1,0, 1,1,0
10590 unsigned short locboxelements[6*2*3] =
10595 12,13,14, 12,14,15,
10596 16,17,18, 16,18,19,
10600 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10603 cl_locnode_t *loc = (cl_locnode_t *)ent;
10605 float vertex3f[6*4*3];
10607 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10608 GL_DepthMask(false);
10609 GL_DepthRange(0, 1);
10610 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10611 GL_DepthTest(true);
10612 GL_CullFace(GL_NONE);
10613 R_EntityMatrix(&identitymatrix);
10615 // R_Mesh_ResetTextureState();
10617 i = surfacelist[0];
10618 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10619 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10620 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10621 surfacelist[0] < 0 ? 0.5f : 0.125f);
10623 if (VectorCompare(loc->mins, loc->maxs))
10625 VectorSet(size, 2, 2, 2);
10626 VectorMA(loc->mins, -0.5f, size, mins);
10630 VectorCopy(loc->mins, mins);
10631 VectorSubtract(loc->maxs, loc->mins, size);
10634 for (i = 0;i < 6*4*3;)
10635 for (j = 0;j < 3;j++, i++)
10636 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10638 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10639 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10640 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10643 void R_DrawLocs(void)
10646 cl_locnode_t *loc, *nearestloc;
10648 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10649 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10651 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10652 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10656 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10658 if (decalsystem->decals)
10659 Mem_Free(decalsystem->decals);
10660 memset(decalsystem, 0, sizeof(*decalsystem));
10663 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)
10666 tridecal_t *decals;
10669 // expand or initialize the system
10670 if (decalsystem->maxdecals <= decalsystem->numdecals)
10672 decalsystem_t old = *decalsystem;
10673 qboolean useshortelements;
10674 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10675 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10676 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)));
10677 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10678 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10679 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10680 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10681 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10682 if (decalsystem->numdecals)
10683 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10685 Mem_Free(old.decals);
10686 for (i = 0;i < decalsystem->maxdecals*3;i++)
10687 decalsystem->element3i[i] = i;
10688 if (useshortelements)
10689 for (i = 0;i < decalsystem->maxdecals*3;i++)
10690 decalsystem->element3s[i] = i;
10693 // grab a decal and search for another free slot for the next one
10694 decals = decalsystem->decals;
10695 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10696 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10698 decalsystem->freedecal = i;
10699 if (decalsystem->numdecals <= i)
10700 decalsystem->numdecals = i + 1;
10702 // initialize the decal
10704 decal->triangleindex = triangleindex;
10705 decal->surfaceindex = surfaceindex;
10706 decal->decalsequence = decalsequence;
10707 decal->color4f[0][0] = c0[0];
10708 decal->color4f[0][1] = c0[1];
10709 decal->color4f[0][2] = c0[2];
10710 decal->color4f[0][3] = 1;
10711 decal->color4f[1][0] = c1[0];
10712 decal->color4f[1][1] = c1[1];
10713 decal->color4f[1][2] = c1[2];
10714 decal->color4f[1][3] = 1;
10715 decal->color4f[2][0] = c2[0];
10716 decal->color4f[2][1] = c2[1];
10717 decal->color4f[2][2] = c2[2];
10718 decal->color4f[2][3] = 1;
10719 decal->vertex3f[0][0] = v0[0];
10720 decal->vertex3f[0][1] = v0[1];
10721 decal->vertex3f[0][2] = v0[2];
10722 decal->vertex3f[1][0] = v1[0];
10723 decal->vertex3f[1][1] = v1[1];
10724 decal->vertex3f[1][2] = v1[2];
10725 decal->vertex3f[2][0] = v2[0];
10726 decal->vertex3f[2][1] = v2[1];
10727 decal->vertex3f[2][2] = v2[2];
10728 decal->texcoord2f[0][0] = t0[0];
10729 decal->texcoord2f[0][1] = t0[1];
10730 decal->texcoord2f[1][0] = t1[0];
10731 decal->texcoord2f[1][1] = t1[1];
10732 decal->texcoord2f[2][0] = t2[0];
10733 decal->texcoord2f[2][1] = t2[1];
10734 TriangleNormal(v0, v1, v2, decal->plane);
10735 VectorNormalize(decal->plane);
10736 decal->plane[3] = DotProduct(v0, decal->plane);
10739 extern cvar_t cl_decals_bias;
10740 extern cvar_t cl_decals_models;
10741 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10742 // baseparms, parms, temps
10743 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)
10748 const float *vertex3f;
10749 const float *normal3f;
10751 float points[2][9][3];
10758 e = rsurface.modelelement3i + 3*triangleindex;
10760 vertex3f = rsurface.modelvertex3f;
10761 normal3f = rsurface.modelnormal3f;
10765 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10767 index = 3*e[cornerindex];
10768 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10773 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10775 index = 3*e[cornerindex];
10776 VectorCopy(vertex3f + index, v[cornerindex]);
10781 //TriangleNormal(v[0], v[1], v[2], normal);
10782 //if (DotProduct(normal, localnormal) < 0.0f)
10784 // clip by each of the box planes formed from the projection matrix
10785 // if anything survives, we emit the decal
10786 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]);
10789 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]);
10792 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]);
10795 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]);
10798 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]);
10801 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]);
10804 // some part of the triangle survived, so we have to accept it...
10807 // dynamic always uses the original triangle
10809 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10811 index = 3*e[cornerindex];
10812 VectorCopy(vertex3f + index, v[cornerindex]);
10815 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10817 // convert vertex positions to texcoords
10818 Matrix4x4_Transform(projection, v[cornerindex], temp);
10819 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10820 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10821 // calculate distance fade from the projection origin
10822 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10823 f = bound(0.0f, f, 1.0f);
10824 c[cornerindex][0] = r * f;
10825 c[cornerindex][1] = g * f;
10826 c[cornerindex][2] = b * f;
10827 c[cornerindex][3] = 1.0f;
10828 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10831 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);
10833 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10834 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);
10836 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)
10838 matrix4x4_t projection;
10839 decalsystem_t *decalsystem;
10842 const msurface_t *surface;
10843 const msurface_t *surfaces;
10844 const int *surfacelist;
10845 const texture_t *texture;
10847 int numsurfacelist;
10848 int surfacelistindex;
10851 float localorigin[3];
10852 float localnormal[3];
10853 float localmins[3];
10854 float localmaxs[3];
10857 float planes[6][4];
10860 int bih_triangles_count;
10861 int bih_triangles[256];
10862 int bih_surfaces[256];
10864 decalsystem = &ent->decalsystem;
10865 model = ent->model;
10866 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10868 R_DecalSystem_Reset(&ent->decalsystem);
10872 if (!model->brush.data_leafs && !cl_decals_models.integer)
10874 if (decalsystem->model)
10875 R_DecalSystem_Reset(decalsystem);
10879 if (decalsystem->model != model)
10880 R_DecalSystem_Reset(decalsystem);
10881 decalsystem->model = model;
10883 RSurf_ActiveModelEntity(ent, true, false, false);
10885 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10886 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10887 VectorNormalize(localnormal);
10888 localsize = worldsize*rsurface.inversematrixscale;
10889 localmins[0] = localorigin[0] - localsize;
10890 localmins[1] = localorigin[1] - localsize;
10891 localmins[2] = localorigin[2] - localsize;
10892 localmaxs[0] = localorigin[0] + localsize;
10893 localmaxs[1] = localorigin[1] + localsize;
10894 localmaxs[2] = localorigin[2] + localsize;
10896 //VectorCopy(localnormal, planes[4]);
10897 //VectorVectors(planes[4], planes[2], planes[0]);
10898 AnglesFromVectors(angles, localnormal, NULL, false);
10899 AngleVectors(angles, planes[0], planes[2], planes[4]);
10900 VectorNegate(planes[0], planes[1]);
10901 VectorNegate(planes[2], planes[3]);
10902 VectorNegate(planes[4], planes[5]);
10903 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10904 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10905 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10906 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10907 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10908 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10913 matrix4x4_t forwardprojection;
10914 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10915 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10920 float projectionvector[4][3];
10921 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10922 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10923 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10924 projectionvector[0][0] = planes[0][0] * ilocalsize;
10925 projectionvector[0][1] = planes[1][0] * ilocalsize;
10926 projectionvector[0][2] = planes[2][0] * ilocalsize;
10927 projectionvector[1][0] = planes[0][1] * ilocalsize;
10928 projectionvector[1][1] = planes[1][1] * ilocalsize;
10929 projectionvector[1][2] = planes[2][1] * ilocalsize;
10930 projectionvector[2][0] = planes[0][2] * ilocalsize;
10931 projectionvector[2][1] = planes[1][2] * ilocalsize;
10932 projectionvector[2][2] = planes[2][2] * ilocalsize;
10933 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10934 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10935 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10936 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10940 dynamic = model->surfmesh.isanimated;
10941 numsurfacelist = model->nummodelsurfaces;
10942 surfacelist = model->sortedmodelsurfaces;
10943 surfaces = model->data_surfaces;
10946 bih_triangles_count = -1;
10949 if(model->render_bih.numleafs)
10950 bih = &model->render_bih;
10951 else if(model->collision_bih.numleafs)
10952 bih = &model->collision_bih;
10955 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10956 if(bih_triangles_count == 0)
10958 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10960 if(bih_triangles_count > 0)
10962 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10964 surfaceindex = bih_surfaces[triangleindex];
10965 surface = surfaces + surfaceindex;
10966 texture = surface->texture;
10967 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10969 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10971 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10976 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10978 surfaceindex = surfacelist[surfacelistindex];
10979 surface = surfaces + surfaceindex;
10980 // check cull box first because it rejects more than any other check
10981 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10983 // skip transparent surfaces
10984 texture = surface->texture;
10985 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10987 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10989 numtriangles = surface->num_triangles;
10990 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10991 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10996 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10997 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)
10999 int renderentityindex;
11000 float worldmins[3];
11001 float worldmaxs[3];
11002 entity_render_t *ent;
11004 if (!cl_decals_newsystem.integer)
11007 worldmins[0] = worldorigin[0] - worldsize;
11008 worldmins[1] = worldorigin[1] - worldsize;
11009 worldmins[2] = worldorigin[2] - worldsize;
11010 worldmaxs[0] = worldorigin[0] + worldsize;
11011 worldmaxs[1] = worldorigin[1] + worldsize;
11012 worldmaxs[2] = worldorigin[2] + worldsize;
11014 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11016 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11018 ent = r_refdef.scene.entities[renderentityindex];
11019 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11022 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11026 typedef struct r_decalsystem_splatqueue_s
11028 vec3_t worldorigin;
11029 vec3_t worldnormal;
11035 r_decalsystem_splatqueue_t;
11037 int r_decalsystem_numqueued = 0;
11038 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11040 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)
11042 r_decalsystem_splatqueue_t *queue;
11044 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11047 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11048 VectorCopy(worldorigin, queue->worldorigin);
11049 VectorCopy(worldnormal, queue->worldnormal);
11050 Vector4Set(queue->color, r, g, b, a);
11051 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11052 queue->worldsize = worldsize;
11053 queue->decalsequence = cl.decalsequence++;
11056 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11059 r_decalsystem_splatqueue_t *queue;
11061 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11062 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);
11063 r_decalsystem_numqueued = 0;
11066 extern cvar_t cl_decals_max;
11067 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11070 decalsystem_t *decalsystem = &ent->decalsystem;
11077 if (!decalsystem->numdecals)
11080 if (r_showsurfaces.integer)
11083 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11085 R_DecalSystem_Reset(decalsystem);
11089 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11090 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11092 if (decalsystem->lastupdatetime)
11093 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11096 decalsystem->lastupdatetime = r_refdef.scene.time;
11097 decal = decalsystem->decals;
11098 numdecals = decalsystem->numdecals;
11100 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11102 if (decal->color4f[0][3])
11104 decal->lived += frametime;
11105 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11107 memset(decal, 0, sizeof(*decal));
11108 if (decalsystem->freedecal > i)
11109 decalsystem->freedecal = i;
11113 decal = decalsystem->decals;
11114 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11117 // collapse the array by shuffling the tail decals into the gaps
11120 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11121 decalsystem->freedecal++;
11122 if (decalsystem->freedecal == numdecals)
11124 decal[decalsystem->freedecal] = decal[--numdecals];
11127 decalsystem->numdecals = numdecals;
11129 if (numdecals <= 0)
11131 // if there are no decals left, reset decalsystem
11132 R_DecalSystem_Reset(decalsystem);
11136 extern skinframe_t *decalskinframe;
11137 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11140 decalsystem_t *decalsystem = &ent->decalsystem;
11149 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11152 numdecals = decalsystem->numdecals;
11156 if (r_showsurfaces.integer)
11159 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11161 R_DecalSystem_Reset(decalsystem);
11165 // if the model is static it doesn't matter what value we give for
11166 // wantnormals and wanttangents, so this logic uses only rules applicable
11167 // to a model, knowing that they are meaningless otherwise
11168 if (ent == r_refdef.scene.worldentity)
11169 RSurf_ActiveWorldEntity();
11171 RSurf_ActiveModelEntity(ent, false, false, false);
11173 decalsystem->lastupdatetime = r_refdef.scene.time;
11174 decal = decalsystem->decals;
11176 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11178 // update vertex positions for animated models
11179 v3f = decalsystem->vertex3f;
11180 c4f = decalsystem->color4f;
11181 t2f = decalsystem->texcoord2f;
11182 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11184 if (!decal->color4f[0][3])
11187 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11191 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11194 // update color values for fading decals
11195 if (decal->lived >= cl_decals_time.value)
11196 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11200 c4f[ 0] = decal->color4f[0][0] * alpha;
11201 c4f[ 1] = decal->color4f[0][1] * alpha;
11202 c4f[ 2] = decal->color4f[0][2] * alpha;
11204 c4f[ 4] = decal->color4f[1][0] * alpha;
11205 c4f[ 5] = decal->color4f[1][1] * alpha;
11206 c4f[ 6] = decal->color4f[1][2] * alpha;
11208 c4f[ 8] = decal->color4f[2][0] * alpha;
11209 c4f[ 9] = decal->color4f[2][1] * alpha;
11210 c4f[10] = decal->color4f[2][2] * alpha;
11213 t2f[0] = decal->texcoord2f[0][0];
11214 t2f[1] = decal->texcoord2f[0][1];
11215 t2f[2] = decal->texcoord2f[1][0];
11216 t2f[3] = decal->texcoord2f[1][1];
11217 t2f[4] = decal->texcoord2f[2][0];
11218 t2f[5] = decal->texcoord2f[2][1];
11220 // update vertex positions for animated models
11221 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11223 e = rsurface.modelelement3i + 3*decal->triangleindex;
11224 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11225 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11226 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11230 VectorCopy(decal->vertex3f[0], v3f);
11231 VectorCopy(decal->vertex3f[1], v3f + 3);
11232 VectorCopy(decal->vertex3f[2], v3f + 6);
11235 if (r_refdef.fogenabled)
11237 alpha = RSurf_FogVertex(v3f);
11238 VectorScale(c4f, alpha, c4f);
11239 alpha = RSurf_FogVertex(v3f + 3);
11240 VectorScale(c4f + 4, alpha, c4f + 4);
11241 alpha = RSurf_FogVertex(v3f + 6);
11242 VectorScale(c4f + 8, alpha, c4f + 8);
11253 r_refdef.stats.drawndecals += numtris;
11255 // now render the decals all at once
11256 // (this assumes they all use one particle font texture!)
11257 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);
11258 // R_Mesh_ResetTextureState();
11259 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11260 GL_DepthMask(false);
11261 GL_DepthRange(0, 1);
11262 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11263 GL_DepthTest(true);
11264 GL_CullFace(GL_NONE);
11265 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11266 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11267 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11271 static void R_DrawModelDecals(void)
11275 // fade faster when there are too many decals
11276 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11277 for (i = 0;i < r_refdef.scene.numentities;i++)
11278 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11280 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11281 for (i = 0;i < r_refdef.scene.numentities;i++)
11282 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11283 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11285 R_DecalSystem_ApplySplatEntitiesQueue();
11287 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11288 for (i = 0;i < r_refdef.scene.numentities;i++)
11289 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11291 r_refdef.stats.totaldecals += numdecals;
11293 if (r_showsurfaces.integer)
11296 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11298 for (i = 0;i < r_refdef.scene.numentities;i++)
11300 if (!r_refdef.viewcache.entityvisible[i])
11302 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11303 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11307 extern cvar_t mod_collision_bih;
11308 void R_DrawDebugModel(void)
11310 entity_render_t *ent = rsurface.entity;
11311 int i, j, k, l, flagsmask;
11312 const msurface_t *surface;
11313 dp_model_t *model = ent->model;
11316 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11319 if (r_showoverdraw.value > 0)
11321 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11322 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11323 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11324 GL_DepthTest(false);
11325 GL_DepthMask(false);
11326 GL_DepthRange(0, 1);
11327 GL_BlendFunc(GL_ONE, GL_ONE);
11328 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11330 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11332 rsurface.texture = R_GetCurrentTexture(surface->texture);
11333 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11335 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11336 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11337 if (!rsurface.texture->currentlayers->depthmask)
11338 GL_Color(c, 0, 0, 1.0f);
11339 else if (ent == r_refdef.scene.worldentity)
11340 GL_Color(c, c, c, 1.0f);
11342 GL_Color(0, c, 0, 1.0f);
11343 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11347 rsurface.texture = NULL;
11350 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11352 // R_Mesh_ResetTextureState();
11353 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11354 GL_DepthRange(0, 1);
11355 GL_DepthTest(!r_showdisabledepthtest.integer);
11356 GL_DepthMask(false);
11357 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11359 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11363 qboolean cullbox = ent == r_refdef.scene.worldentity;
11364 const q3mbrush_t *brush;
11365 const bih_t *bih = &model->collision_bih;
11366 const bih_leaf_t *bihleaf;
11367 float vertex3f[3][3];
11368 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11370 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11372 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11374 switch (bihleaf->type)
11377 brush = model->brush.data_brushes + bihleaf->itemindex;
11378 if (brush->colbrushf && brush->colbrushf->numtriangles)
11380 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);
11381 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11382 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11385 case BIH_COLLISIONTRIANGLE:
11386 triangleindex = bihleaf->itemindex;
11387 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11388 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11389 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11390 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);
11391 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11392 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11394 case BIH_RENDERTRIANGLE:
11395 triangleindex = bihleaf->itemindex;
11396 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11397 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11398 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11399 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);
11400 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11401 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11407 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11410 if (r_showtris.integer && qglPolygonMode)
11412 if (r_showdisabledepthtest.integer)
11414 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11415 GL_DepthMask(false);
11419 GL_BlendFunc(GL_ONE, GL_ZERO);
11420 GL_DepthMask(true);
11422 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11423 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11425 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11427 rsurface.texture = R_GetCurrentTexture(surface->texture);
11428 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11430 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11431 if (!rsurface.texture->currentlayers->depthmask)
11432 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11433 else if (ent == r_refdef.scene.worldentity)
11434 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11436 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11437 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11441 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11442 rsurface.texture = NULL;
11445 if (r_shownormals.value != 0 && qglBegin)
11447 if (r_showdisabledepthtest.integer)
11449 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11450 GL_DepthMask(false);
11454 GL_BlendFunc(GL_ONE, GL_ZERO);
11455 GL_DepthMask(true);
11457 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11459 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11461 rsurface.texture = R_GetCurrentTexture(surface->texture);
11462 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11464 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11465 qglBegin(GL_LINES);
11466 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11468 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11470 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11471 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11472 qglVertex3f(v[0], v[1], v[2]);
11473 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11474 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11475 qglVertex3f(v[0], v[1], v[2]);
11478 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11480 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11482 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11483 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11484 qglVertex3f(v[0], v[1], v[2]);
11485 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11486 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11487 qglVertex3f(v[0], v[1], v[2]);
11490 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11492 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11494 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11495 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11496 qglVertex3f(v[0], v[1], v[2]);
11497 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11498 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11499 qglVertex3f(v[0], v[1], v[2]);
11502 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11504 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11506 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11507 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11508 qglVertex3f(v[0], v[1], v[2]);
11509 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11510 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11511 qglVertex3f(v[0], v[1], v[2]);
11518 rsurface.texture = NULL;
11523 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11524 int r_maxsurfacelist = 0;
11525 const msurface_t **r_surfacelist = NULL;
11526 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11528 int i, j, endj, flagsmask;
11529 dp_model_t *model = r_refdef.scene.worldmodel;
11530 msurface_t *surfaces;
11531 unsigned char *update;
11532 int numsurfacelist = 0;
11536 if (r_maxsurfacelist < model->num_surfaces)
11538 r_maxsurfacelist = model->num_surfaces;
11540 Mem_Free((msurface_t**)r_surfacelist);
11541 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11544 RSurf_ActiveWorldEntity();
11546 surfaces = model->data_surfaces;
11547 update = model->brushq1.lightmapupdateflags;
11549 // update light styles on this submodel
11550 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11552 model_brush_lightstyleinfo_t *style;
11553 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11555 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11557 int *list = style->surfacelist;
11558 style->value = r_refdef.scene.lightstylevalue[style->style];
11559 for (j = 0;j < style->numsurfaces;j++)
11560 update[list[j]] = true;
11565 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11569 R_DrawDebugModel();
11570 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11574 rsurface.lightmaptexture = NULL;
11575 rsurface.deluxemaptexture = NULL;
11576 rsurface.uselightmaptexture = false;
11577 rsurface.texture = NULL;
11578 rsurface.rtlight = NULL;
11579 numsurfacelist = 0;
11580 // add visible surfaces to draw list
11581 for (i = 0;i < model->nummodelsurfaces;i++)
11583 j = model->sortedmodelsurfaces[i];
11584 if (r_refdef.viewcache.world_surfacevisible[j])
11585 r_surfacelist[numsurfacelist++] = surfaces + j;
11587 // update lightmaps if needed
11588 if (model->brushq1.firstrender)
11590 model->brushq1.firstrender = false;
11591 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11593 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11597 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11598 if (r_refdef.viewcache.world_surfacevisible[j])
11600 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11602 // don't do anything if there were no surfaces
11603 if (!numsurfacelist)
11605 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11608 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11610 // add to stats if desired
11611 if (r_speeds.integer && !skysurfaces && !depthonly)
11613 r_refdef.stats.world_surfaces += numsurfacelist;
11614 for (j = 0;j < numsurfacelist;j++)
11615 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11618 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11621 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11623 int i, j, endj, flagsmask;
11624 dp_model_t *model = ent->model;
11625 msurface_t *surfaces;
11626 unsigned char *update;
11627 int numsurfacelist = 0;
11631 if (r_maxsurfacelist < model->num_surfaces)
11633 r_maxsurfacelist = model->num_surfaces;
11635 Mem_Free((msurface_t **)r_surfacelist);
11636 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11639 // if the model is static it doesn't matter what value we give for
11640 // wantnormals and wanttangents, so this logic uses only rules applicable
11641 // to a model, knowing that they are meaningless otherwise
11642 if (ent == r_refdef.scene.worldentity)
11643 RSurf_ActiveWorldEntity();
11644 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11645 RSurf_ActiveModelEntity(ent, false, false, false);
11647 RSurf_ActiveModelEntity(ent, true, true, true);
11648 else if (depthonly)
11650 switch (vid.renderpath)
11652 case RENDERPATH_GL20:
11653 case RENDERPATH_D3D9:
11654 case RENDERPATH_D3D10:
11655 case RENDERPATH_D3D11:
11656 case RENDERPATH_SOFT:
11657 case RENDERPATH_GLES2:
11658 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11660 case RENDERPATH_GL11:
11661 case RENDERPATH_GL13:
11662 case RENDERPATH_GLES1:
11663 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11669 switch (vid.renderpath)
11671 case RENDERPATH_GL20:
11672 case RENDERPATH_D3D9:
11673 case RENDERPATH_D3D10:
11674 case RENDERPATH_D3D11:
11675 case RENDERPATH_SOFT:
11676 case RENDERPATH_GLES2:
11677 RSurf_ActiveModelEntity(ent, true, true, false);
11679 case RENDERPATH_GL11:
11680 case RENDERPATH_GL13:
11681 case RENDERPATH_GLES1:
11682 RSurf_ActiveModelEntity(ent, true, false, false);
11687 surfaces = model->data_surfaces;
11688 update = model->brushq1.lightmapupdateflags;
11690 // update light styles
11691 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11693 model_brush_lightstyleinfo_t *style;
11694 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11696 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11698 int *list = style->surfacelist;
11699 style->value = r_refdef.scene.lightstylevalue[style->style];
11700 for (j = 0;j < style->numsurfaces;j++)
11701 update[list[j]] = true;
11706 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11710 R_DrawDebugModel();
11711 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11715 rsurface.lightmaptexture = NULL;
11716 rsurface.deluxemaptexture = NULL;
11717 rsurface.uselightmaptexture = false;
11718 rsurface.texture = NULL;
11719 rsurface.rtlight = NULL;
11720 numsurfacelist = 0;
11721 // add visible surfaces to draw list
11722 for (i = 0;i < model->nummodelsurfaces;i++)
11723 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11724 // don't do anything if there were no surfaces
11725 if (!numsurfacelist)
11727 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11730 // update lightmaps if needed
11734 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11739 R_BuildLightMap(ent, surfaces + j);
11744 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11746 R_BuildLightMap(ent, surfaces + j);
11747 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11749 // add to stats if desired
11750 if (r_speeds.integer && !skysurfaces && !depthonly)
11752 r_refdef.stats.entities_surfaces += numsurfacelist;
11753 for (j = 0;j < numsurfacelist;j++)
11754 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11757 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11760 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11762 static texture_t texture;
11763 static msurface_t surface;
11764 const msurface_t *surfacelist = &surface;
11766 // fake enough texture and surface state to render this geometry
11768 texture.update_lastrenderframe = -1; // regenerate this texture
11769 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11770 texture.currentskinframe = skinframe;
11771 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11772 texture.offsetmapping = OFFSETMAPPING_OFF;
11773 texture.offsetscale = 1;
11774 texture.specularscalemod = 1;
11775 texture.specularpowermod = 1;
11777 surface.texture = &texture;
11778 surface.num_triangles = numtriangles;
11779 surface.num_firsttriangle = firsttriangle;
11780 surface.num_vertices = numvertices;
11781 surface.num_firstvertex = firstvertex;
11784 rsurface.texture = R_GetCurrentTexture(surface.texture);
11785 rsurface.lightmaptexture = NULL;
11786 rsurface.deluxemaptexture = NULL;
11787 rsurface.uselightmaptexture = false;
11788 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11791 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)
11793 static msurface_t surface;
11794 const msurface_t *surfacelist = &surface;
11796 // fake enough texture and surface state to render this geometry
11797 surface.texture = texture;
11798 surface.num_triangles = numtriangles;
11799 surface.num_firsttriangle = firsttriangle;
11800 surface.num_vertices = numvertices;
11801 surface.num_firstvertex = firstvertex;
11804 rsurface.texture = R_GetCurrentTexture(surface.texture);
11805 rsurface.lightmaptexture = NULL;
11806 rsurface.deluxemaptexture = NULL;
11807 rsurface.uselightmaptexture = false;
11808 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);