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 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#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 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1920 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1921 else if (texturemode == GL_ADD)
1922 permutation |= SHADERPERMUTATION_GLOW;
1923 else if (texturemode == GL_DECAL)
1924 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1926 texturemode = GL_MODULATE;
1927 if (vid.allowalphatocoverage)
1928 GL_AlphaToCoverage(false);
1929 switch (vid.renderpath)
1931 case RENDERPATH_D3D9:
1933 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1934 R_Mesh_TexBind(GL20TU_FIRST , first );
1935 R_Mesh_TexBind(GL20TU_SECOND, second);
1936 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1937 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1940 case RENDERPATH_D3D10:
1941 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1943 case RENDERPATH_D3D11:
1944 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1946 case RENDERPATH_GL20:
1947 case RENDERPATH_GLES2:
1948 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1949 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1950 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1951 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1952 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1954 case RENDERPATH_GL13:
1955 case RENDERPATH_GLES1:
1956 R_Mesh_TexBind(0, first );
1957 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1958 R_Mesh_TexBind(1, second);
1960 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1962 case RENDERPATH_GL11:
1963 R_Mesh_TexBind(0, first );
1965 case RENDERPATH_SOFT:
1966 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1967 R_Mesh_TexBind(GL20TU_FIRST , first );
1968 R_Mesh_TexBind(GL20TU_SECOND, second);
1973 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1975 unsigned int permutation = 0;
1976 if (r_trippy.integer && !notrippy)
1977 permutation |= SHADERPERMUTATION_TRIPPY;
1978 if (vid.allowalphatocoverage)
1979 GL_AlphaToCoverage(false);
1980 switch (vid.renderpath)
1982 case RENDERPATH_D3D9:
1984 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1987 case RENDERPATH_D3D10:
1988 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990 case RENDERPATH_D3D11:
1991 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1993 case RENDERPATH_GL20:
1994 case RENDERPATH_GLES2:
1995 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1997 case RENDERPATH_GL13:
1998 case RENDERPATH_GLES1:
1999 R_Mesh_TexBind(0, 0);
2000 R_Mesh_TexBind(1, 0);
2002 case RENDERPATH_GL11:
2003 R_Mesh_TexBind(0, 0);
2005 case RENDERPATH_SOFT:
2006 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2011 void R_SetupShader_ShowDepth(qboolean notrippy)
2013 int permutation = 0;
2014 if (r_trippy.integer && !notrippy)
2015 permutation |= SHADERPERMUTATION_TRIPPY;
2016 if (vid.allowalphatocoverage)
2017 GL_AlphaToCoverage(false);
2018 switch (vid.renderpath)
2020 case RENDERPATH_D3D9:
2022 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2025 case RENDERPATH_D3D10:
2026 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2028 case RENDERPATH_D3D11:
2029 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2031 case RENDERPATH_GL20:
2032 case RENDERPATH_GLES2:
2033 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2035 case RENDERPATH_GL13:
2036 case RENDERPATH_GLES1:
2038 case RENDERPATH_GL11:
2040 case RENDERPATH_SOFT:
2041 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2046 extern qboolean r_shadow_usingdeferredprepass;
2047 extern cvar_t r_shadow_deferred_8bitrange;
2048 extern rtexture_t *r_shadow_attenuationgradienttexture;
2049 extern rtexture_t *r_shadow_attenuation2dtexture;
2050 extern rtexture_t *r_shadow_attenuation3dtexture;
2051 extern qboolean r_shadow_usingshadowmap2d;
2052 extern qboolean r_shadow_usingshadowmaportho;
2053 extern float r_shadow_shadowmap_texturescale[2];
2054 extern float r_shadow_shadowmap_parameters[4];
2055 extern qboolean r_shadow_shadowmapvsdct;
2056 extern qboolean r_shadow_shadowmapsampler;
2057 extern int r_shadow_shadowmappcf;
2058 extern rtexture_t *r_shadow_shadowmap2dtexture;
2059 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2060 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2061 extern matrix4x4_t r_shadow_shadowmapmatrix;
2062 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2063 extern int r_shadow_prepass_width;
2064 extern int r_shadow_prepass_height;
2065 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2066 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2067 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2068 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2069 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2071 #define BLENDFUNC_ALLOWS_COLORMOD 1
2072 #define BLENDFUNC_ALLOWS_FOG 2
2073 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2074 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2075 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2076 static int R_BlendFuncFlags(int src, int dst)
2080 // a blendfunc allows colormod if:
2081 // a) it can never keep the destination pixel invariant, or
2082 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2083 // this is to prevent unintended side effects from colormod
2085 // a blendfunc allows fog if:
2086 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2087 // this is to prevent unintended side effects from fog
2089 // these checks are the output of fogeval.pl
2091 r |= BLENDFUNC_ALLOWS_COLORMOD;
2092 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2093 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2094 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2095 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2096 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2097 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2100 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2101 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2102 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2103 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2104 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2105 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2106 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2107 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2111 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2112 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2117 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2119 // select a permutation of the lighting shader appropriate to this
2120 // combination of texture, entity, light source, and fogging, only use the
2121 // minimum features necessary to avoid wasting rendering time in the
2122 // fragment shader on features that are not being used
2123 unsigned int permutation = 0;
2124 unsigned int mode = 0;
2126 static float dummy_colormod[3] = {1, 1, 1};
2127 float *colormod = rsurface.colormod;
2129 matrix4x4_t tempmatrix;
2130 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2131 if (r_trippy.integer && !notrippy)
2132 permutation |= SHADERPERMUTATION_TRIPPY;
2133 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2134 permutation |= SHADERPERMUTATION_ALPHAKILL;
2135 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2136 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2137 if (rsurfacepass == RSURFPASS_BACKGROUND)
2139 // distorted background
2140 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2142 mode = SHADERMODE_WATER;
2143 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2145 // this is the right thing to do for wateralpha
2146 GL_BlendFunc(GL_ONE, GL_ZERO);
2147 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2151 // this is the right thing to do for entity alpha
2152 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2153 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2156 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2158 mode = SHADERMODE_REFRACTION;
2159 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2160 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2164 mode = SHADERMODE_GENERIC;
2165 permutation |= SHADERPERMUTATION_DIFFUSE;
2166 GL_BlendFunc(GL_ONE, GL_ZERO);
2167 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2169 if (vid.allowalphatocoverage)
2170 GL_AlphaToCoverage(false);
2172 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2174 if (r_glsl_offsetmapping.integer)
2176 switch(rsurface.texture->offsetmapping)
2178 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2179 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2180 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2181 case OFFSETMAPPING_OFF: break;
2184 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2185 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2186 // normalmap (deferred prepass), may use alpha test on diffuse
2187 mode = SHADERMODE_DEFERREDGEOMETRY;
2188 GL_BlendFunc(GL_ONE, GL_ZERO);
2189 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2190 if (vid.allowalphatocoverage)
2191 GL_AlphaToCoverage(false);
2193 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2195 if (r_glsl_offsetmapping.integer)
2197 switch(rsurface.texture->offsetmapping)
2199 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2200 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202 case OFFSETMAPPING_OFF: break;
2205 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2206 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2208 mode = SHADERMODE_LIGHTSOURCE;
2209 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2210 permutation |= SHADERPERMUTATION_CUBEFILTER;
2211 if (diffusescale > 0)
2212 permutation |= SHADERPERMUTATION_DIFFUSE;
2213 if (specularscale > 0)
2214 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2215 if (r_refdef.fogenabled)
2216 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2217 if (rsurface.texture->colormapping)
2218 permutation |= SHADERPERMUTATION_COLORMAPPING;
2219 if (r_shadow_usingshadowmap2d)
2221 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2222 if(r_shadow_shadowmapvsdct)
2223 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2225 if (r_shadow_shadowmapsampler)
2226 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2227 if (r_shadow_shadowmappcf > 1)
2228 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2229 else if (r_shadow_shadowmappcf)
2230 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2232 if (rsurface.texture->reflectmasktexture)
2233 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2234 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2235 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2236 if (vid.allowalphatocoverage)
2237 GL_AlphaToCoverage(false);
2239 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2241 if (r_glsl_offsetmapping.integer)
2243 switch(rsurface.texture->offsetmapping)
2245 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2246 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2247 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2248 case OFFSETMAPPING_OFF: break;
2251 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2252 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2253 // unshaded geometry (fullbright or ambient model lighting)
2254 mode = SHADERMODE_FLATCOLOR;
2255 ambientscale = diffusescale = specularscale = 0;
2256 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2257 permutation |= SHADERPERMUTATION_GLOW;
2258 if (r_refdef.fogenabled)
2259 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2260 if (rsurface.texture->colormapping)
2261 permutation |= SHADERPERMUTATION_COLORMAPPING;
2262 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2264 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2265 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2267 if (r_shadow_shadowmapsampler)
2268 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2269 if (r_shadow_shadowmappcf > 1)
2270 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2271 else if (r_shadow_shadowmappcf)
2272 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2274 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2275 permutation |= SHADERPERMUTATION_REFLECTION;
2276 if (rsurface.texture->reflectmasktexture)
2277 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2278 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2279 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2280 // when using alphatocoverage, we don't need alphakill
2281 if (vid.allowalphatocoverage)
2283 if (r_transparent_alphatocoverage.integer)
2285 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2286 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2289 GL_AlphaToCoverage(false);
2292 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2294 if (r_glsl_offsetmapping.integer)
2296 switch(rsurface.texture->offsetmapping)
2298 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2299 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301 case OFFSETMAPPING_OFF: break;
2304 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2305 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2306 // directional model lighting
2307 mode = SHADERMODE_LIGHTDIRECTION;
2308 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2309 permutation |= SHADERPERMUTATION_GLOW;
2310 permutation |= SHADERPERMUTATION_DIFFUSE;
2311 if (specularscale > 0)
2312 permutation |= SHADERPERMUTATION_SPECULAR;
2313 if (r_refdef.fogenabled)
2314 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2315 if (rsurface.texture->colormapping)
2316 permutation |= SHADERPERMUTATION_COLORMAPPING;
2317 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2319 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2320 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2322 if (r_shadow_shadowmapsampler)
2323 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2324 if (r_shadow_shadowmappcf > 1)
2325 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2326 else if (r_shadow_shadowmappcf)
2327 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2329 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2330 permutation |= SHADERPERMUTATION_REFLECTION;
2331 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2332 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2333 if (rsurface.texture->reflectmasktexture)
2334 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2335 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2337 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2338 if (r_shadow_bouncegriddirectional)
2339 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2341 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343 // when using alphatocoverage, we don't need alphakill
2344 if (vid.allowalphatocoverage)
2346 if (r_transparent_alphatocoverage.integer)
2348 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2349 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2352 GL_AlphaToCoverage(false);
2355 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2357 if (r_glsl_offsetmapping.integer)
2359 switch(rsurface.texture->offsetmapping)
2361 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2362 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2363 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2364 case OFFSETMAPPING_OFF: break;
2367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2368 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2369 // ambient model lighting
2370 mode = SHADERMODE_LIGHTDIRECTION;
2371 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2372 permutation |= SHADERPERMUTATION_GLOW;
2373 if (r_refdef.fogenabled)
2374 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2375 if (rsurface.texture->colormapping)
2376 permutation |= SHADERPERMUTATION_COLORMAPPING;
2377 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2379 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2380 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2382 if (r_shadow_shadowmapsampler)
2383 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2384 if (r_shadow_shadowmappcf > 1)
2385 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2386 else if (r_shadow_shadowmappcf)
2387 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2389 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2390 permutation |= SHADERPERMUTATION_REFLECTION;
2391 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2392 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2393 if (rsurface.texture->reflectmasktexture)
2394 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2395 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2397 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2398 if (r_shadow_bouncegriddirectional)
2399 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2401 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2402 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2403 // when using alphatocoverage, we don't need alphakill
2404 if (vid.allowalphatocoverage)
2406 if (r_transparent_alphatocoverage.integer)
2408 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2409 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2412 GL_AlphaToCoverage(false);
2417 if (r_glsl_offsetmapping.integer)
2419 switch(rsurface.texture->offsetmapping)
2421 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2422 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2423 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2424 case OFFSETMAPPING_OFF: break;
2427 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2428 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2430 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2431 permutation |= SHADERPERMUTATION_GLOW;
2432 if (r_refdef.fogenabled)
2433 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2434 if (rsurface.texture->colormapping)
2435 permutation |= SHADERPERMUTATION_COLORMAPPING;
2436 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2438 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2439 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2441 if (r_shadow_shadowmapsampler)
2442 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2443 if (r_shadow_shadowmappcf > 1)
2444 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2445 else if (r_shadow_shadowmappcf)
2446 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2448 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2449 permutation |= SHADERPERMUTATION_REFLECTION;
2450 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2451 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2452 if (rsurface.texture->reflectmasktexture)
2453 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2454 if (FAKELIGHT_ENABLED)
2456 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2457 mode = SHADERMODE_FAKELIGHT;
2458 permutation |= SHADERPERMUTATION_DIFFUSE;
2459 if (specularscale > 0)
2460 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2462 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2464 // deluxemapping (light direction texture)
2465 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2466 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2468 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2469 permutation |= SHADERPERMUTATION_DIFFUSE;
2470 if (specularscale > 0)
2471 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2473 else if (r_glsl_deluxemapping.integer >= 2)
2475 // fake deluxemapping (uniform light direction in tangentspace)
2476 if (rsurface.uselightmaptexture)
2477 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2479 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2480 permutation |= SHADERPERMUTATION_DIFFUSE;
2481 if (specularscale > 0)
2482 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2484 else if (rsurface.uselightmaptexture)
2486 // ordinary lightmapping (q1bsp, q3bsp)
2487 mode = SHADERMODE_LIGHTMAP;
2491 // ordinary vertex coloring (q3bsp)
2492 mode = SHADERMODE_VERTEXCOLOR;
2494 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2496 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2497 if (r_shadow_bouncegriddirectional)
2498 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2500 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2501 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2502 // when using alphatocoverage, we don't need alphakill
2503 if (vid.allowalphatocoverage)
2505 if (r_transparent_alphatocoverage.integer)
2507 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2508 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2511 GL_AlphaToCoverage(false);
2514 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2515 colormod = dummy_colormod;
2516 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2517 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2518 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2519 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2520 switch(vid.renderpath)
2522 case RENDERPATH_D3D9:
2524 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2525 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2526 R_SetupShader_SetPermutationHLSL(mode, permutation);
2527 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2528 if (mode == SHADERMODE_LIGHTSOURCE)
2530 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2531 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2535 if (mode == SHADERMODE_LIGHTDIRECTION)
2537 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2540 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2541 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2542 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2543 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2544 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2546 if (mode == SHADERMODE_LIGHTSOURCE)
2548 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2549 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2550 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2551 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2552 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2554 // additive passes are only darkened by fog, not tinted
2555 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2556 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
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 * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2595 if (mode == SHADERMODE_WATER)
2596 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2598 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2599 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2600 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2601 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2602 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2603 if (rsurface.texture->pantstexture)
2604 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2606 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2607 if (rsurface.texture->shirttexture)
2608 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2610 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2611 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2612 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2613 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2614 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2615 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2616 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2617 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2618 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2619 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2621 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2622 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2624 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2625 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2626 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2627 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2628 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2629 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2630 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2631 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2632 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2633 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2634 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2635 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2636 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2637 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2638 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2639 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2640 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2641 if (rsurfacepass == RSURFPASS_BACKGROUND)
2643 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2644 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2645 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2649 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2651 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2652 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2653 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2654 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2655 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2657 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2658 if (rsurface.rtlight)
2660 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2661 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2666 case RENDERPATH_D3D10:
2667 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2669 case RENDERPATH_D3D11:
2670 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2672 case RENDERPATH_GL20:
2673 case RENDERPATH_GLES2:
2674 if (!vid.useinterleavedarrays)
2676 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2677 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2678 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2679 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2680 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2681 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2682 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2683 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2687 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2688 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2690 R_SetupShader_SetPermutationGLSL(mode, permutation);
2691 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2692 if (mode == SHADERMODE_LIGHTSOURCE)
2694 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2695 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2696 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2697 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2698 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2699 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2701 // additive passes are only darkened by fog, not tinted
2702 if (r_glsl_permutation->loc_FogColor >= 0)
2703 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2704 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2708 if (mode == SHADERMODE_FLATCOLOR)
2710 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2712 else if (mode == SHADERMODE_LIGHTDIRECTION)
2714 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2715 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2716 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2717 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2718 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2719 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2720 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2724 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2725 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2726 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2727 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2728 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2730 // additive passes are only darkened by fog, not tinted
2731 if (r_glsl_permutation->loc_FogColor >= 0)
2733 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2734 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2736 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2738 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2739 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2740 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2741 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2742 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2743 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2744 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2745 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2746 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2748 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2749 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2750 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2751 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2752 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2754 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2755 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2756 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2757 if (r_glsl_permutation->loc_Color_Pants >= 0)
2759 if (rsurface.texture->pantstexture)
2760 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2762 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2764 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2766 if (rsurface.texture->shirttexture)
2767 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2769 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2771 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2772 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2773 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2774 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2775 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2776 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2777 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2778 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2779 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2781 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2782 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2783 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2784 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2786 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2787 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2788 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2789 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2790 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2791 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2792 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2793 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2794 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2795 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2796 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2797 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2798 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2799 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2800 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2801 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2802 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2803 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2804 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2805 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2806 if (rsurfacepass == RSURFPASS_BACKGROUND)
2808 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2809 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2810 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2814 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2816 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2817 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2818 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2819 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2820 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2822 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2823 if (rsurface.rtlight)
2825 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2826 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2829 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2832 case RENDERPATH_GL11:
2833 case RENDERPATH_GL13:
2834 case RENDERPATH_GLES1:
2836 case RENDERPATH_SOFT:
2837 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2838 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2839 R_SetupShader_SetPermutationSoft(mode, permutation);
2840 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2841 if (mode == SHADERMODE_LIGHTSOURCE)
2843 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2844 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2845 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2846 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2847 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2848 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2850 // additive passes are only darkened by fog, not tinted
2851 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2852 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2856 if (mode == SHADERMODE_FLATCOLOR)
2858 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2860 else if (mode == SHADERMODE_LIGHTDIRECTION)
2862 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2863 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2864 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2865 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2866 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2867 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2868 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2872 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2873 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2874 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2875 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2876 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2878 // additive passes are only darkened by fog, not tinted
2879 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2880 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2882 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2883 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2884 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2885 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2886 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2887 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2888 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2889 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2890 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2891 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2893 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2894 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2895 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2896 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2897 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2899 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2900 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2901 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2902 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2904 if (rsurface.texture->pantstexture)
2905 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2907 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2909 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2911 if (rsurface.texture->shirttexture)
2912 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2914 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2916 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2917 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2918 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2919 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2920 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2921 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2922 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2923 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2924 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2926 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2927 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2929 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2930 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2931 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2932 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2933 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2934 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2935 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2936 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2937 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2938 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2939 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2940 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2941 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2942 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2943 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2944 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2945 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2946 if (rsurfacepass == RSURFPASS_BACKGROUND)
2948 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2949 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2950 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2954 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2956 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2957 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2958 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2959 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2960 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2962 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2963 if (rsurface.rtlight)
2965 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2966 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2973 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2975 // select a permutation of the lighting shader appropriate to this
2976 // combination of texture, entity, light source, and fogging, only use the
2977 // minimum features necessary to avoid wasting rendering time in the
2978 // fragment shader on features that are not being used
2979 unsigned int permutation = 0;
2980 unsigned int mode = 0;
2981 const float *lightcolorbase = rtlight->currentcolor;
2982 float ambientscale = rtlight->ambientscale;
2983 float diffusescale = rtlight->diffusescale;
2984 float specularscale = rtlight->specularscale;
2985 // this is the location of the light in view space
2986 vec3_t viewlightorigin;
2987 // this transforms from view space (camera) to light space (cubemap)
2988 matrix4x4_t viewtolight;
2989 matrix4x4_t lighttoview;
2990 float viewtolight16f[16];
2991 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2993 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2994 if (rtlight->currentcubemap != r_texture_whitecube)
2995 permutation |= SHADERPERMUTATION_CUBEFILTER;
2996 if (diffusescale > 0)
2997 permutation |= SHADERPERMUTATION_DIFFUSE;
2998 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2999 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3000 if (r_shadow_usingshadowmap2d)
3002 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3003 if (r_shadow_shadowmapvsdct)
3004 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3006 if (r_shadow_shadowmapsampler)
3007 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3008 if (r_shadow_shadowmappcf > 1)
3009 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3010 else if (r_shadow_shadowmappcf)
3011 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3013 if (vid.allowalphatocoverage)
3014 GL_AlphaToCoverage(false);
3015 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3016 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3017 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3018 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3019 switch(vid.renderpath)
3021 case RENDERPATH_D3D9:
3023 R_SetupShader_SetPermutationHLSL(mode, permutation);
3024 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3025 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3026 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3027 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3028 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3029 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3030 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3031 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3032 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3033 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3035 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3036 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3037 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3038 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3039 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3040 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3043 case RENDERPATH_D3D10:
3044 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3046 case RENDERPATH_D3D11:
3047 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3049 case RENDERPATH_GL20:
3050 case RENDERPATH_GLES2:
3051 R_SetupShader_SetPermutationGLSL(mode, permutation);
3052 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3053 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3054 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3055 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3056 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3057 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3058 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3059 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3060 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3061 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3063 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3064 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3065 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3066 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3067 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3068 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3070 case RENDERPATH_GL11:
3071 case RENDERPATH_GL13:
3072 case RENDERPATH_GLES1:
3074 case RENDERPATH_SOFT:
3075 R_SetupShader_SetPermutationGLSL(mode, permutation);
3076 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3077 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3078 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3079 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3080 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3081 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3082 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3083 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
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;
7881 // lightmaps mode looks bad with dlights using actual texturing, so turn
7882 // off the colormap and glossmap, but leave the normalmap on as it still
7883 // accurately represents the shading involved
7884 if (gl_lightmaps.integer)
7886 t->basetexture = r_texture_grey128;
7887 t->pantstexture = r_texture_black;
7888 t->shirttexture = r_texture_black;
7889 t->nmaptexture = r_texture_blanknormalmap;
7890 t->glosstexture = r_texture_black;
7891 t->glowtexture = NULL;
7892 t->fogtexture = NULL;
7893 t->reflectmasktexture = NULL;
7894 t->backgroundbasetexture = NULL;
7895 t->backgroundnmaptexture = r_texture_blanknormalmap;
7896 t->backgroundglosstexture = r_texture_black;
7897 t->backgroundglowtexture = NULL;
7898 t->specularscale = 0;
7899 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7902 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7903 VectorClear(t->dlightcolor);
7904 t->currentnumlayers = 0;
7905 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7907 int blendfunc1, blendfunc2;
7909 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7911 blendfunc1 = GL_SRC_ALPHA;
7912 blendfunc2 = GL_ONE;
7914 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7916 blendfunc1 = GL_SRC_ALPHA;
7917 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7919 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7921 blendfunc1 = t->customblendfunc[0];
7922 blendfunc2 = t->customblendfunc[1];
7926 blendfunc1 = GL_ONE;
7927 blendfunc2 = GL_ZERO;
7929 // don't colormod evilblend textures
7930 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7931 VectorSet(t->lightmapcolor, 1, 1, 1);
7932 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7933 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7935 // fullbright is not affected by r_refdef.lightmapintensity
7936 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]);
7937 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7938 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]);
7939 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7940 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]);
7944 vec3_t ambientcolor;
7946 // set the color tint used for lights affecting this surface
7947 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7949 // q3bsp has no lightmap updates, so the lightstylevalue that
7950 // would normally be baked into the lightmap must be
7951 // applied to the color
7952 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7953 if (model->type == mod_brushq3)
7954 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7955 colorscale *= r_refdef.lightmapintensity;
7956 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7957 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7958 // basic lit geometry
7959 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]);
7960 // add pants/shirt if needed
7961 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7962 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]);
7963 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7964 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]);
7965 // now add ambient passes if needed
7966 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7968 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]);
7969 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7970 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]);
7971 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7972 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]);
7975 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7976 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]);
7977 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7979 // if this is opaque use alpha blend which will darken the earlier
7982 // if this is an alpha blended material, all the earlier passes
7983 // were darkened by fog already, so we only need to add the fog
7984 // color ontop through the fog mask texture
7986 // if this is an additive blended material, all the earlier passes
7987 // were darkened by fog already, and we should not add fog color
7988 // (because the background was not darkened, there is no fog color
7989 // that was lost behind it).
7990 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]);
7994 return t->currentframe;
7997 rsurfacestate_t rsurface;
7999 void RSurf_ActiveWorldEntity(void)
8001 dp_model_t *model = r_refdef.scene.worldmodel;
8002 //if (rsurface.entity == r_refdef.scene.worldentity)
8004 rsurface.entity = r_refdef.scene.worldentity;
8005 rsurface.skeleton = NULL;
8006 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8007 rsurface.ent_skinnum = 0;
8008 rsurface.ent_qwskin = -1;
8009 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8010 rsurface.shadertime = r_refdef.scene.time;
8011 rsurface.matrix = identitymatrix;
8012 rsurface.inversematrix = identitymatrix;
8013 rsurface.matrixscale = 1;
8014 rsurface.inversematrixscale = 1;
8015 R_EntityMatrix(&identitymatrix);
8016 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8017 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8018 rsurface.fograngerecip = r_refdef.fograngerecip;
8019 rsurface.fogheightfade = r_refdef.fogheightfade;
8020 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8021 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8022 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8023 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8024 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8025 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8026 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8027 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8028 rsurface.colormod[3] = 1;
8029 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);
8030 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8031 rsurface.frameblend[0].lerp = 1;
8032 rsurface.ent_alttextures = false;
8033 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8034 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8035 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8036 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8037 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8038 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8039 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8040 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8041 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8042 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8043 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8044 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8045 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8046 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8047 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8048 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8049 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8050 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8051 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8052 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8053 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8054 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8055 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8056 rsurface.modelelement3i = model->surfmesh.data_element3i;
8057 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8058 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8059 rsurface.modelelement3s = model->surfmesh.data_element3s;
8060 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8061 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8062 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8063 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8064 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8065 rsurface.modelsurfaces = model->data_surfaces;
8066 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8067 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8068 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8069 rsurface.modelgeneratedvertex = false;
8070 rsurface.batchgeneratedvertex = false;
8071 rsurface.batchfirstvertex = 0;
8072 rsurface.batchnumvertices = 0;
8073 rsurface.batchfirsttriangle = 0;
8074 rsurface.batchnumtriangles = 0;
8075 rsurface.batchvertex3f = NULL;
8076 rsurface.batchvertex3f_vertexbuffer = NULL;
8077 rsurface.batchvertex3f_bufferoffset = 0;
8078 rsurface.batchsvector3f = NULL;
8079 rsurface.batchsvector3f_vertexbuffer = NULL;
8080 rsurface.batchsvector3f_bufferoffset = 0;
8081 rsurface.batchtvector3f = NULL;
8082 rsurface.batchtvector3f_vertexbuffer = NULL;
8083 rsurface.batchtvector3f_bufferoffset = 0;
8084 rsurface.batchnormal3f = NULL;
8085 rsurface.batchnormal3f_vertexbuffer = NULL;
8086 rsurface.batchnormal3f_bufferoffset = 0;
8087 rsurface.batchlightmapcolor4f = NULL;
8088 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8089 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8090 rsurface.batchtexcoordtexture2f = NULL;
8091 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8092 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8093 rsurface.batchtexcoordlightmap2f = NULL;
8094 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8095 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8096 rsurface.batchvertexmesh = NULL;
8097 rsurface.batchvertexmeshbuffer = NULL;
8098 rsurface.batchvertex3fbuffer = NULL;
8099 rsurface.batchelement3i = NULL;
8100 rsurface.batchelement3i_indexbuffer = NULL;
8101 rsurface.batchelement3i_bufferoffset = 0;
8102 rsurface.batchelement3s = NULL;
8103 rsurface.batchelement3s_indexbuffer = NULL;
8104 rsurface.batchelement3s_bufferoffset = 0;
8105 rsurface.passcolor4f = NULL;
8106 rsurface.passcolor4f_vertexbuffer = NULL;
8107 rsurface.passcolor4f_bufferoffset = 0;
8110 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8112 dp_model_t *model = ent->model;
8113 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8115 rsurface.entity = (entity_render_t *)ent;
8116 rsurface.skeleton = ent->skeleton;
8117 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8118 rsurface.ent_skinnum = ent->skinnum;
8119 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;
8120 rsurface.ent_flags = ent->flags;
8121 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8122 rsurface.matrix = ent->matrix;
8123 rsurface.inversematrix = ent->inversematrix;
8124 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8125 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8126 R_EntityMatrix(&rsurface.matrix);
8127 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8128 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8129 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8130 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8131 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8132 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8133 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8134 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8135 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8136 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8137 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8138 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8139 rsurface.colormod[3] = ent->alpha;
8140 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8141 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8142 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8143 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8144 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8145 if (ent->model->brush.submodel && !prepass)
8147 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8148 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8150 if (model->surfmesh.isanimated && model->AnimateVertices)
8152 if (ent->animcache_vertex3f)
8154 rsurface.modelvertex3f = ent->animcache_vertex3f;
8155 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8156 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8157 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8158 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8159 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8160 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8162 else if (wanttangents)
8164 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8165 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8166 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8167 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8168 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8169 rsurface.modelvertexmesh = NULL;
8170 rsurface.modelvertexmeshbuffer = NULL;
8171 rsurface.modelvertex3fbuffer = NULL;
8173 else if (wantnormals)
8175 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8176 rsurface.modelsvector3f = NULL;
8177 rsurface.modeltvector3f = NULL;
8178 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8179 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8180 rsurface.modelvertexmesh = NULL;
8181 rsurface.modelvertexmeshbuffer = NULL;
8182 rsurface.modelvertex3fbuffer = NULL;
8186 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8187 rsurface.modelsvector3f = NULL;
8188 rsurface.modeltvector3f = NULL;
8189 rsurface.modelnormal3f = NULL;
8190 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8191 rsurface.modelvertexmesh = NULL;
8192 rsurface.modelvertexmeshbuffer = NULL;
8193 rsurface.modelvertex3fbuffer = NULL;
8195 rsurface.modelvertex3f_vertexbuffer = 0;
8196 rsurface.modelvertex3f_bufferoffset = 0;
8197 rsurface.modelsvector3f_vertexbuffer = 0;
8198 rsurface.modelsvector3f_bufferoffset = 0;
8199 rsurface.modeltvector3f_vertexbuffer = 0;
8200 rsurface.modeltvector3f_bufferoffset = 0;
8201 rsurface.modelnormal3f_vertexbuffer = 0;
8202 rsurface.modelnormal3f_bufferoffset = 0;
8203 rsurface.modelgeneratedvertex = true;
8207 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8208 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8209 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8210 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8211 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8212 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8213 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8214 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8215 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8216 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8217 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8218 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8219 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8220 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8221 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8222 rsurface.modelgeneratedvertex = false;
8224 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8225 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8226 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8227 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8228 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8229 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8230 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8231 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8232 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8233 rsurface.modelelement3i = model->surfmesh.data_element3i;
8234 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8235 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8236 rsurface.modelelement3s = model->surfmesh.data_element3s;
8237 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8238 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8239 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8240 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8241 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8242 rsurface.modelsurfaces = model->data_surfaces;
8243 rsurface.batchgeneratedvertex = false;
8244 rsurface.batchfirstvertex = 0;
8245 rsurface.batchnumvertices = 0;
8246 rsurface.batchfirsttriangle = 0;
8247 rsurface.batchnumtriangles = 0;
8248 rsurface.batchvertex3f = NULL;
8249 rsurface.batchvertex3f_vertexbuffer = NULL;
8250 rsurface.batchvertex3f_bufferoffset = 0;
8251 rsurface.batchsvector3f = NULL;
8252 rsurface.batchsvector3f_vertexbuffer = NULL;
8253 rsurface.batchsvector3f_bufferoffset = 0;
8254 rsurface.batchtvector3f = NULL;
8255 rsurface.batchtvector3f_vertexbuffer = NULL;
8256 rsurface.batchtvector3f_bufferoffset = 0;
8257 rsurface.batchnormal3f = NULL;
8258 rsurface.batchnormal3f_vertexbuffer = NULL;
8259 rsurface.batchnormal3f_bufferoffset = 0;
8260 rsurface.batchlightmapcolor4f = NULL;
8261 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8262 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8263 rsurface.batchtexcoordtexture2f = NULL;
8264 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8265 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8266 rsurface.batchtexcoordlightmap2f = NULL;
8267 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8268 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8269 rsurface.batchvertexmesh = NULL;
8270 rsurface.batchvertexmeshbuffer = NULL;
8271 rsurface.batchvertex3fbuffer = NULL;
8272 rsurface.batchelement3i = NULL;
8273 rsurface.batchelement3i_indexbuffer = NULL;
8274 rsurface.batchelement3i_bufferoffset = 0;
8275 rsurface.batchelement3s = NULL;
8276 rsurface.batchelement3s_indexbuffer = NULL;
8277 rsurface.batchelement3s_bufferoffset = 0;
8278 rsurface.passcolor4f = NULL;
8279 rsurface.passcolor4f_vertexbuffer = NULL;
8280 rsurface.passcolor4f_bufferoffset = 0;
8283 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)
8285 rsurface.entity = r_refdef.scene.worldentity;
8286 rsurface.skeleton = NULL;
8287 rsurface.ent_skinnum = 0;
8288 rsurface.ent_qwskin = -1;
8289 rsurface.ent_flags = entflags;
8290 rsurface.shadertime = r_refdef.scene.time - shadertime;
8291 rsurface.modelnumvertices = numvertices;
8292 rsurface.modelnumtriangles = numtriangles;
8293 rsurface.matrix = *matrix;
8294 rsurface.inversematrix = *inversematrix;
8295 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8296 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8297 R_EntityMatrix(&rsurface.matrix);
8298 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8299 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8300 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8301 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8302 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8303 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8304 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8305 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8306 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8307 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8308 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8309 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8310 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);
8311 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8312 rsurface.frameblend[0].lerp = 1;
8313 rsurface.ent_alttextures = false;
8314 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8315 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8318 rsurface.modelvertex3f = (float *)vertex3f;
8319 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8320 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8321 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8323 else if (wantnormals)
8325 rsurface.modelvertex3f = (float *)vertex3f;
8326 rsurface.modelsvector3f = NULL;
8327 rsurface.modeltvector3f = NULL;
8328 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8332 rsurface.modelvertex3f = (float *)vertex3f;
8333 rsurface.modelsvector3f = NULL;
8334 rsurface.modeltvector3f = NULL;
8335 rsurface.modelnormal3f = NULL;
8337 rsurface.modelvertexmesh = NULL;
8338 rsurface.modelvertexmeshbuffer = NULL;
8339 rsurface.modelvertex3fbuffer = NULL;
8340 rsurface.modelvertex3f_vertexbuffer = 0;
8341 rsurface.modelvertex3f_bufferoffset = 0;
8342 rsurface.modelsvector3f_vertexbuffer = 0;
8343 rsurface.modelsvector3f_bufferoffset = 0;
8344 rsurface.modeltvector3f_vertexbuffer = 0;
8345 rsurface.modeltvector3f_bufferoffset = 0;
8346 rsurface.modelnormal3f_vertexbuffer = 0;
8347 rsurface.modelnormal3f_bufferoffset = 0;
8348 rsurface.modelgeneratedvertex = true;
8349 rsurface.modellightmapcolor4f = (float *)color4f;
8350 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8351 rsurface.modellightmapcolor4f_bufferoffset = 0;
8352 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8353 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8354 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8355 rsurface.modeltexcoordlightmap2f = NULL;
8356 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8357 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8358 rsurface.modelelement3i = (int *)element3i;
8359 rsurface.modelelement3i_indexbuffer = NULL;
8360 rsurface.modelelement3i_bufferoffset = 0;
8361 rsurface.modelelement3s = (unsigned short *)element3s;
8362 rsurface.modelelement3s_indexbuffer = NULL;
8363 rsurface.modelelement3s_bufferoffset = 0;
8364 rsurface.modellightmapoffsets = NULL;
8365 rsurface.modelsurfaces = NULL;
8366 rsurface.batchgeneratedvertex = false;
8367 rsurface.batchfirstvertex = 0;
8368 rsurface.batchnumvertices = 0;
8369 rsurface.batchfirsttriangle = 0;
8370 rsurface.batchnumtriangles = 0;
8371 rsurface.batchvertex3f = NULL;
8372 rsurface.batchvertex3f_vertexbuffer = NULL;
8373 rsurface.batchvertex3f_bufferoffset = 0;
8374 rsurface.batchsvector3f = NULL;
8375 rsurface.batchsvector3f_vertexbuffer = NULL;
8376 rsurface.batchsvector3f_bufferoffset = 0;
8377 rsurface.batchtvector3f = NULL;
8378 rsurface.batchtvector3f_vertexbuffer = NULL;
8379 rsurface.batchtvector3f_bufferoffset = 0;
8380 rsurface.batchnormal3f = NULL;
8381 rsurface.batchnormal3f_vertexbuffer = NULL;
8382 rsurface.batchnormal3f_bufferoffset = 0;
8383 rsurface.batchlightmapcolor4f = NULL;
8384 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8385 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8386 rsurface.batchtexcoordtexture2f = NULL;
8387 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8388 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8389 rsurface.batchtexcoordlightmap2f = NULL;
8390 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8391 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8392 rsurface.batchvertexmesh = NULL;
8393 rsurface.batchvertexmeshbuffer = NULL;
8394 rsurface.batchvertex3fbuffer = NULL;
8395 rsurface.batchelement3i = NULL;
8396 rsurface.batchelement3i_indexbuffer = NULL;
8397 rsurface.batchelement3i_bufferoffset = 0;
8398 rsurface.batchelement3s = NULL;
8399 rsurface.batchelement3s_indexbuffer = NULL;
8400 rsurface.batchelement3s_bufferoffset = 0;
8401 rsurface.passcolor4f = NULL;
8402 rsurface.passcolor4f_vertexbuffer = NULL;
8403 rsurface.passcolor4f_bufferoffset = 0;
8405 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8407 if ((wantnormals || wanttangents) && !normal3f)
8409 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8410 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8412 if (wanttangents && !svector3f)
8414 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8415 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8416 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8421 float RSurf_FogPoint(const float *v)
8423 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8424 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8425 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8426 float FogHeightFade = r_refdef.fogheightfade;
8428 unsigned int fogmasktableindex;
8429 if (r_refdef.fogplaneviewabove)
8430 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8432 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8433 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8434 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8437 float RSurf_FogVertex(const float *v)
8439 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8440 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8441 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8442 float FogHeightFade = rsurface.fogheightfade;
8444 unsigned int fogmasktableindex;
8445 if (r_refdef.fogplaneviewabove)
8446 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8448 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8449 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8450 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8453 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8456 for (i = 0;i < numelements;i++)
8457 outelement3i[i] = inelement3i[i] + adjust;
8460 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8461 extern cvar_t gl_vbo;
8462 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8470 int surfacefirsttriangle;
8471 int surfacenumtriangles;
8472 int surfacefirstvertex;
8473 int surfaceendvertex;
8474 int surfacenumvertices;
8475 int batchnumvertices;
8476 int batchnumtriangles;
8480 qboolean dynamicvertex;
8484 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8486 q3shaderinfo_deform_t *deform;
8487 const msurface_t *surface, *firstsurface;
8488 r_vertexmesh_t *vertexmesh;
8489 if (!texturenumsurfaces)
8491 // find vertex range of this surface batch
8493 firstsurface = texturesurfacelist[0];
8494 firsttriangle = firstsurface->num_firsttriangle;
8495 batchnumvertices = 0;
8496 batchnumtriangles = 0;
8497 firstvertex = endvertex = firstsurface->num_firstvertex;
8498 for (i = 0;i < texturenumsurfaces;i++)
8500 surface = texturesurfacelist[i];
8501 if (surface != firstsurface + i)
8503 surfacefirstvertex = surface->num_firstvertex;
8504 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8505 surfacenumvertices = surface->num_vertices;
8506 surfacenumtriangles = surface->num_triangles;
8507 if (firstvertex > surfacefirstvertex)
8508 firstvertex = surfacefirstvertex;
8509 if (endvertex < surfaceendvertex)
8510 endvertex = surfaceendvertex;
8511 batchnumvertices += surfacenumvertices;
8512 batchnumtriangles += surfacenumtriangles;
8515 // we now know the vertex range used, and if there are any gaps in it
8516 rsurface.batchfirstvertex = firstvertex;
8517 rsurface.batchnumvertices = endvertex - firstvertex;
8518 rsurface.batchfirsttriangle = firsttriangle;
8519 rsurface.batchnumtriangles = batchnumtriangles;
8521 // this variable holds flags for which properties have been updated that
8522 // may require regenerating vertexmesh array...
8525 // check if any dynamic vertex processing must occur
8526 dynamicvertex = false;
8528 // if there is a chance of animated vertex colors, it's a dynamic batch
8529 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8531 dynamicvertex = true;
8532 batchneed |= BATCHNEED_NOGAPS;
8533 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8536 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8538 switch (deform->deform)
8541 case Q3DEFORM_PROJECTIONSHADOW:
8542 case Q3DEFORM_TEXT0:
8543 case Q3DEFORM_TEXT1:
8544 case Q3DEFORM_TEXT2:
8545 case Q3DEFORM_TEXT3:
8546 case Q3DEFORM_TEXT4:
8547 case Q3DEFORM_TEXT5:
8548 case Q3DEFORM_TEXT6:
8549 case Q3DEFORM_TEXT7:
8552 case Q3DEFORM_AUTOSPRITE:
8553 dynamicvertex = true;
8554 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8555 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8557 case Q3DEFORM_AUTOSPRITE2:
8558 dynamicvertex = true;
8559 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8560 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8562 case Q3DEFORM_NORMAL:
8563 dynamicvertex = true;
8564 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8565 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8568 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8569 break; // if wavefunc is a nop, ignore this transform
8570 dynamicvertex = true;
8571 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8572 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8574 case Q3DEFORM_BULGE:
8575 dynamicvertex = true;
8576 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8577 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8580 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8581 break; // if wavefunc is a nop, ignore this transform
8582 dynamicvertex = true;
8583 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8584 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8588 switch(rsurface.texture->tcgen.tcgen)
8591 case Q3TCGEN_TEXTURE:
8593 case Q3TCGEN_LIGHTMAP:
8594 dynamicvertex = true;
8595 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8596 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8598 case Q3TCGEN_VECTOR:
8599 dynamicvertex = true;
8600 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8601 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8603 case Q3TCGEN_ENVIRONMENT:
8604 dynamicvertex = true;
8605 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8606 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8609 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8611 dynamicvertex = true;
8612 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8613 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8616 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8618 dynamicvertex = true;
8619 batchneed |= BATCHNEED_NOGAPS;
8620 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8623 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8625 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8626 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8627 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8628 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8629 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8630 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8631 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8634 // when the model data has no vertex buffer (dynamic mesh), we need to
8636 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8637 batchneed |= BATCHNEED_NOGAPS;
8639 // if needsupdate, we have to do a dynamic vertex batch for sure
8640 if (needsupdate & batchneed)
8641 dynamicvertex = true;
8643 // see if we need to build vertexmesh from arrays
8644 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8645 dynamicvertex = true;
8647 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8648 // also some drivers strongly dislike firstvertex
8649 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8650 dynamicvertex = true;
8652 rsurface.batchvertex3f = rsurface.modelvertex3f;
8653 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8654 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8655 rsurface.batchsvector3f = rsurface.modelsvector3f;
8656 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8657 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8658 rsurface.batchtvector3f = rsurface.modeltvector3f;
8659 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8660 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8661 rsurface.batchnormal3f = rsurface.modelnormal3f;
8662 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8663 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8664 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8665 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8666 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8667 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8668 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8669 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8670 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8671 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8672 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8673 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8674 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8675 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8676 rsurface.batchelement3i = rsurface.modelelement3i;
8677 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8678 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8679 rsurface.batchelement3s = rsurface.modelelement3s;
8680 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8681 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8683 // if any dynamic vertex processing has to occur in software, we copy the
8684 // entire surface list together before processing to rebase the vertices
8685 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8687 // if any gaps exist and we do not have a static vertex buffer, we have to
8688 // copy the surface list together to avoid wasting upload bandwidth on the
8689 // vertices in the gaps.
8691 // if gaps exist and we have a static vertex buffer, we still have to
8692 // combine the index buffer ranges into one dynamic index buffer.
8694 // in all cases we end up with data that can be drawn in one call.
8698 // static vertex data, just set pointers...
8699 rsurface.batchgeneratedvertex = false;
8700 // if there are gaps, we want to build a combined index buffer,
8701 // otherwise use the original static buffer with an appropriate offset
8704 // build a new triangle elements array for this batch
8705 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8706 rsurface.batchfirsttriangle = 0;
8708 for (i = 0;i < texturenumsurfaces;i++)
8710 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8711 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8712 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8713 numtriangles += surfacenumtriangles;
8715 rsurface.batchelement3i_indexbuffer = NULL;
8716 rsurface.batchelement3i_bufferoffset = 0;
8717 rsurface.batchelement3s = NULL;
8718 rsurface.batchelement3s_indexbuffer = NULL;
8719 rsurface.batchelement3s_bufferoffset = 0;
8720 if (endvertex <= 65536)
8722 // make a 16bit (unsigned short) index array if possible
8723 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8724 for (i = 0;i < numtriangles*3;i++)
8725 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8731 // something needs software processing, do it for real...
8732 // we only directly handle separate array data in this case and then
8733 // generate interleaved data if needed...
8734 rsurface.batchgeneratedvertex = true;
8736 // now copy the vertex data into a combined array and make an index array
8737 // (this is what Quake3 does all the time)
8738 //if (gaps || rsurface.batchfirstvertex)
8740 rsurface.batchvertex3fbuffer = NULL;
8741 rsurface.batchvertexmesh = NULL;
8742 rsurface.batchvertexmeshbuffer = NULL;
8743 rsurface.batchvertex3f = NULL;
8744 rsurface.batchvertex3f_vertexbuffer = NULL;
8745 rsurface.batchvertex3f_bufferoffset = 0;
8746 rsurface.batchsvector3f = NULL;
8747 rsurface.batchsvector3f_vertexbuffer = NULL;
8748 rsurface.batchsvector3f_bufferoffset = 0;
8749 rsurface.batchtvector3f = NULL;
8750 rsurface.batchtvector3f_vertexbuffer = NULL;
8751 rsurface.batchtvector3f_bufferoffset = 0;
8752 rsurface.batchnormal3f = NULL;
8753 rsurface.batchnormal3f_vertexbuffer = NULL;
8754 rsurface.batchnormal3f_bufferoffset = 0;
8755 rsurface.batchlightmapcolor4f = NULL;
8756 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8757 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8758 rsurface.batchtexcoordtexture2f = NULL;
8759 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8760 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8761 rsurface.batchtexcoordlightmap2f = NULL;
8762 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8763 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8764 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8765 rsurface.batchelement3i_indexbuffer = NULL;
8766 rsurface.batchelement3i_bufferoffset = 0;
8767 rsurface.batchelement3s = NULL;
8768 rsurface.batchelement3s_indexbuffer = NULL;
8769 rsurface.batchelement3s_bufferoffset = 0;
8770 // we'll only be setting up certain arrays as needed
8771 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8772 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8773 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8774 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8775 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8776 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8777 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8779 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8780 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8782 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8783 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8784 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8785 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8786 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8787 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8790 for (i = 0;i < texturenumsurfaces;i++)
8792 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8793 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8794 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8795 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8796 // copy only the data requested
8797 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8798 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8799 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8801 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8803 if (rsurface.batchvertex3f)
8804 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8806 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8808 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8810 if (rsurface.modelnormal3f)
8811 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8813 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8815 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8817 if (rsurface.modelsvector3f)
8819 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8820 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8824 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8825 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8828 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8830 if (rsurface.modellightmapcolor4f)
8831 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8833 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8835 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8837 if (rsurface.modeltexcoordtexture2f)
8838 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8840 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8842 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8844 if (rsurface.modeltexcoordlightmap2f)
8845 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8847 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8850 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8851 numvertices += surfacenumvertices;
8852 numtriangles += surfacenumtriangles;
8855 // generate a 16bit index array as well if possible
8856 // (in general, dynamic batches fit)
8857 if (numvertices <= 65536)
8859 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8860 for (i = 0;i < numtriangles*3;i++)
8861 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8864 // since we've copied everything, the batch now starts at 0
8865 rsurface.batchfirstvertex = 0;
8866 rsurface.batchnumvertices = batchnumvertices;
8867 rsurface.batchfirsttriangle = 0;
8868 rsurface.batchnumtriangles = batchnumtriangles;
8871 // q1bsp surfaces rendered in vertex color mode have to have colors
8872 // calculated based on lightstyles
8873 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8875 // generate color arrays for the surfaces in this list
8880 const unsigned char *lm;
8881 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8882 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8883 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8885 for (i = 0;i < texturenumsurfaces;i++)
8887 surface = texturesurfacelist[i];
8888 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8889 surfacenumvertices = surface->num_vertices;
8890 if (surface->lightmapinfo->samples)
8892 for (j = 0;j < surfacenumvertices;j++)
8894 lm = surface->lightmapinfo->samples + offsets[j];
8895 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8896 VectorScale(lm, scale, c);
8897 if (surface->lightmapinfo->styles[1] != 255)
8899 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8901 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8902 VectorMA(c, scale, lm, c);
8903 if (surface->lightmapinfo->styles[2] != 255)
8906 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8907 VectorMA(c, scale, lm, c);
8908 if (surface->lightmapinfo->styles[3] != 255)
8911 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8912 VectorMA(c, scale, lm, c);
8919 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);
8925 for (j = 0;j < surfacenumvertices;j++)
8927 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8934 // if vertices are deformed (sprite flares and things in maps, possibly
8935 // water waves, bulges and other deformations), modify the copied vertices
8937 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8939 switch (deform->deform)
8942 case Q3DEFORM_PROJECTIONSHADOW:
8943 case Q3DEFORM_TEXT0:
8944 case Q3DEFORM_TEXT1:
8945 case Q3DEFORM_TEXT2:
8946 case Q3DEFORM_TEXT3:
8947 case Q3DEFORM_TEXT4:
8948 case Q3DEFORM_TEXT5:
8949 case Q3DEFORM_TEXT6:
8950 case Q3DEFORM_TEXT7:
8953 case Q3DEFORM_AUTOSPRITE:
8954 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8955 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8956 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8957 VectorNormalize(newforward);
8958 VectorNormalize(newright);
8959 VectorNormalize(newup);
8960 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8961 // rsurface.batchvertex3f_vertexbuffer = NULL;
8962 // rsurface.batchvertex3f_bufferoffset = 0;
8963 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8964 // rsurface.batchsvector3f_vertexbuffer = NULL;
8965 // rsurface.batchsvector3f_bufferoffset = 0;
8966 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8967 // rsurface.batchtvector3f_vertexbuffer = NULL;
8968 // rsurface.batchtvector3f_bufferoffset = 0;
8969 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8970 // rsurface.batchnormal3f_vertexbuffer = NULL;
8971 // rsurface.batchnormal3f_bufferoffset = 0;
8972 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8973 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8974 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8975 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8976 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);
8977 // a single autosprite surface can contain multiple sprites...
8978 for (j = 0;j < batchnumvertices - 3;j += 4)
8980 VectorClear(center);
8981 for (i = 0;i < 4;i++)
8982 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8983 VectorScale(center, 0.25f, center);
8984 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8985 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8986 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8987 for (i = 0;i < 4;i++)
8989 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8990 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8993 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8994 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8995 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);
8997 case Q3DEFORM_AUTOSPRITE2:
8998 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8999 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9000 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9001 VectorNormalize(newforward);
9002 VectorNormalize(newright);
9003 VectorNormalize(newup);
9004 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9005 // rsurface.batchvertex3f_vertexbuffer = NULL;
9006 // rsurface.batchvertex3f_bufferoffset = 0;
9008 const float *v1, *v2;
9018 memset(shortest, 0, sizeof(shortest));
9019 // a single autosprite surface can contain multiple sprites...
9020 for (j = 0;j < batchnumvertices - 3;j += 4)
9022 VectorClear(center);
9023 for (i = 0;i < 4;i++)
9024 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9025 VectorScale(center, 0.25f, center);
9026 // find the two shortest edges, then use them to define the
9027 // axis vectors for rotating around the central axis
9028 for (i = 0;i < 6;i++)
9030 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9031 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9032 l = VectorDistance2(v1, v2);
9033 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9035 l += (1.0f / 1024.0f);
9036 if (shortest[0].length2 > l || i == 0)
9038 shortest[1] = shortest[0];
9039 shortest[0].length2 = l;
9040 shortest[0].v1 = v1;
9041 shortest[0].v2 = v2;
9043 else if (shortest[1].length2 > l || i == 1)
9045 shortest[1].length2 = l;
9046 shortest[1].v1 = v1;
9047 shortest[1].v2 = v2;
9050 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9051 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9052 // this calculates the right vector from the shortest edge
9053 // and the up vector from the edge midpoints
9054 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9055 VectorNormalize(right);
9056 VectorSubtract(end, start, up);
9057 VectorNormalize(up);
9058 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9059 VectorSubtract(rsurface.localvieworigin, center, forward);
9060 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9061 VectorNegate(forward, forward);
9062 VectorReflect(forward, 0, up, forward);
9063 VectorNormalize(forward);
9064 CrossProduct(up, forward, newright);
9065 VectorNormalize(newright);
9066 // rotate the quad around the up axis vector, this is made
9067 // especially easy by the fact we know the quad is flat,
9068 // so we only have to subtract the center position and
9069 // measure distance along the right vector, and then
9070 // multiply that by the newright vector and add back the
9072 // we also need to subtract the old position to undo the
9073 // displacement from the center, which we do with a
9074 // DotProduct, the subtraction/addition of center is also
9075 // optimized into DotProducts here
9076 l = DotProduct(right, center);
9077 for (i = 0;i < 4;i++)
9079 v1 = rsurface.batchvertex3f + 3*(j+i);
9080 f = DotProduct(right, v1) - l;
9081 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9085 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9087 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9088 // rsurface.batchnormal3f_vertexbuffer = NULL;
9089 // rsurface.batchnormal3f_bufferoffset = 0;
9090 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9092 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9094 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9095 // rsurface.batchsvector3f_vertexbuffer = NULL;
9096 // rsurface.batchsvector3f_bufferoffset = 0;
9097 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9098 // rsurface.batchtvector3f_vertexbuffer = NULL;
9099 // rsurface.batchtvector3f_bufferoffset = 0;
9100 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);
9103 case Q3DEFORM_NORMAL:
9104 // deform the normals to make reflections wavey
9105 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9106 rsurface.batchnormal3f_vertexbuffer = NULL;
9107 rsurface.batchnormal3f_bufferoffset = 0;
9108 for (j = 0;j < batchnumvertices;j++)
9111 float *normal = rsurface.batchnormal3f + 3*j;
9112 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9113 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9114 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9115 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9116 VectorNormalize(normal);
9118 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9120 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9121 // rsurface.batchsvector3f_vertexbuffer = NULL;
9122 // rsurface.batchsvector3f_bufferoffset = 0;
9123 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9124 // rsurface.batchtvector3f_vertexbuffer = NULL;
9125 // rsurface.batchtvector3f_bufferoffset = 0;
9126 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9130 // deform vertex array to make wavey water and flags and such
9131 waveparms[0] = deform->waveparms[0];
9132 waveparms[1] = deform->waveparms[1];
9133 waveparms[2] = deform->waveparms[2];
9134 waveparms[3] = deform->waveparms[3];
9135 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9136 break; // if wavefunc is a nop, don't make a dynamic vertex array
9137 // this is how a divisor of vertex influence on deformation
9138 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9139 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9140 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9141 // rsurface.batchvertex3f_vertexbuffer = NULL;
9142 // rsurface.batchvertex3f_bufferoffset = 0;
9143 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9144 // rsurface.batchnormal3f_vertexbuffer = NULL;
9145 // rsurface.batchnormal3f_bufferoffset = 0;
9146 for (j = 0;j < batchnumvertices;j++)
9148 // if the wavefunc depends on time, evaluate it per-vertex
9151 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9152 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9154 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9156 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9157 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9158 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9160 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9161 // rsurface.batchsvector3f_vertexbuffer = NULL;
9162 // rsurface.batchsvector3f_bufferoffset = 0;
9163 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9164 // rsurface.batchtvector3f_vertexbuffer = NULL;
9165 // rsurface.batchtvector3f_bufferoffset = 0;
9166 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);
9169 case Q3DEFORM_BULGE:
9170 // deform vertex array to make the surface have moving bulges
9171 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9172 // rsurface.batchvertex3f_vertexbuffer = NULL;
9173 // rsurface.batchvertex3f_bufferoffset = 0;
9174 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9175 // rsurface.batchnormal3f_vertexbuffer = NULL;
9176 // rsurface.batchnormal3f_bufferoffset = 0;
9177 for (j = 0;j < batchnumvertices;j++)
9179 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9180 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9182 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9183 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9184 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9186 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9187 // rsurface.batchsvector3f_vertexbuffer = NULL;
9188 // rsurface.batchsvector3f_bufferoffset = 0;
9189 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9190 // rsurface.batchtvector3f_vertexbuffer = NULL;
9191 // rsurface.batchtvector3f_bufferoffset = 0;
9192 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9196 // deform vertex array
9197 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9198 break; // if wavefunc is a nop, don't make a dynamic vertex array
9199 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9200 VectorScale(deform->parms, scale, waveparms);
9201 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9202 // rsurface.batchvertex3f_vertexbuffer = NULL;
9203 // rsurface.batchvertex3f_bufferoffset = 0;
9204 for (j = 0;j < batchnumvertices;j++)
9205 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9210 // generate texcoords based on the chosen texcoord source
9211 switch(rsurface.texture->tcgen.tcgen)
9214 case Q3TCGEN_TEXTURE:
9216 case Q3TCGEN_LIGHTMAP:
9217 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9218 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9219 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9220 if (rsurface.batchtexcoordlightmap2f)
9221 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9223 case Q3TCGEN_VECTOR:
9224 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9225 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9226 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9227 for (j = 0;j < batchnumvertices;j++)
9229 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9230 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9233 case Q3TCGEN_ENVIRONMENT:
9234 // make environment reflections using a spheremap
9235 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9236 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9237 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9238 for (j = 0;j < batchnumvertices;j++)
9240 // identical to Q3A's method, but executed in worldspace so
9241 // carried models can be shiny too
9243 float viewer[3], d, reflected[3], worldreflected[3];
9245 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9246 // VectorNormalize(viewer);
9248 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9250 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9251 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9252 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9253 // note: this is proportinal to viewer, so we can normalize later
9255 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9256 VectorNormalize(worldreflected);
9258 // note: this sphere map only uses world x and z!
9259 // so positive and negative y will LOOK THE SAME.
9260 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9261 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9265 // the only tcmod that needs software vertex processing is turbulent, so
9266 // check for it here and apply the changes if needed
9267 // and we only support that as the first one
9268 // (handling a mixture of turbulent and other tcmods would be problematic
9269 // without punting it entirely to a software path)
9270 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9272 amplitude = rsurface.texture->tcmods[0].parms[1];
9273 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9274 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9275 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9276 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9277 for (j = 0;j < batchnumvertices;j++)
9279 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);
9280 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9284 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9286 // convert the modified arrays to vertex structs
9287 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9288 // rsurface.batchvertexmeshbuffer = NULL;
9289 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9290 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9291 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9292 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9293 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9294 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9295 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9297 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9299 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9300 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9303 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9304 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9305 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9306 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9307 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9308 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9309 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9310 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9311 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9315 void RSurf_DrawBatch(void)
9317 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9318 // through the pipeline, killing it earlier in the pipeline would have
9319 // per-surface overhead rather than per-batch overhead, so it's best to
9320 // reject it here, before it hits glDraw.
9321 if (rsurface.batchnumtriangles == 0)
9324 // batch debugging code
9325 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9331 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9332 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9335 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9337 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9339 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9340 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);
9347 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);
9350 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9352 // pick the closest matching water plane
9353 int planeindex, vertexindex, bestplaneindex = -1;
9357 r_waterstate_waterplane_t *p;
9358 qboolean prepared = false;
9360 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9362 if(p->camera_entity != rsurface.texture->camera_entity)
9367 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9369 if(rsurface.batchnumvertices == 0)
9372 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9374 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9375 d += fabs(PlaneDiff(vert, &p->plane));
9377 if (bestd > d || bestplaneindex < 0)
9380 bestplaneindex = planeindex;
9383 return bestplaneindex;
9384 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9385 // this situation though, as it might be better to render single larger
9386 // batches with useless stuff (backface culled for example) than to
9387 // render multiple smaller batches
9390 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9393 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9394 rsurface.passcolor4f_vertexbuffer = 0;
9395 rsurface.passcolor4f_bufferoffset = 0;
9396 for (i = 0;i < rsurface.batchnumvertices;i++)
9397 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9400 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9407 if (rsurface.passcolor4f)
9409 // generate color arrays
9410 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9411 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9412 rsurface.passcolor4f_vertexbuffer = 0;
9413 rsurface.passcolor4f_bufferoffset = 0;
9414 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)
9416 f = RSurf_FogVertex(v);
9425 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9426 rsurface.passcolor4f_vertexbuffer = 0;
9427 rsurface.passcolor4f_bufferoffset = 0;
9428 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9430 f = RSurf_FogVertex(v);
9439 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9446 if (!rsurface.passcolor4f)
9448 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9449 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9450 rsurface.passcolor4f_vertexbuffer = 0;
9451 rsurface.passcolor4f_bufferoffset = 0;
9452 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)
9454 f = RSurf_FogVertex(v);
9455 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9456 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9457 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9462 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9467 if (!rsurface.passcolor4f)
9469 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9470 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9471 rsurface.passcolor4f_vertexbuffer = 0;
9472 rsurface.passcolor4f_bufferoffset = 0;
9473 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9482 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9487 if (!rsurface.passcolor4f)
9489 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9490 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9491 rsurface.passcolor4f_vertexbuffer = 0;
9492 rsurface.passcolor4f_bufferoffset = 0;
9493 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9495 c2[0] = c[0] + r_refdef.scene.ambient;
9496 c2[1] = c[1] + r_refdef.scene.ambient;
9497 c2[2] = c[2] + r_refdef.scene.ambient;
9502 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9505 rsurface.passcolor4f = NULL;
9506 rsurface.passcolor4f_vertexbuffer = 0;
9507 rsurface.passcolor4f_bufferoffset = 0;
9508 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9509 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9510 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9511 GL_Color(r, g, b, a);
9512 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9516 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9518 // TODO: optimize applyfog && applycolor case
9519 // just apply fog if necessary, and tint the fog color array if necessary
9520 rsurface.passcolor4f = NULL;
9521 rsurface.passcolor4f_vertexbuffer = 0;
9522 rsurface.passcolor4f_bufferoffset = 0;
9523 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9524 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9525 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9526 GL_Color(r, g, b, a);
9530 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9533 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9534 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9535 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9536 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9537 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9538 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9539 GL_Color(r, g, b, a);
9543 static void RSurf_DrawBatch_GL11_ClampColor(void)
9548 if (!rsurface.passcolor4f)
9550 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9552 c2[0] = bound(0.0f, c1[0], 1.0f);
9553 c2[1] = bound(0.0f, c1[1], 1.0f);
9554 c2[2] = bound(0.0f, c1[2], 1.0f);
9555 c2[3] = bound(0.0f, c1[3], 1.0f);
9559 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9569 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9570 rsurface.passcolor4f_vertexbuffer = 0;
9571 rsurface.passcolor4f_bufferoffset = 0;
9572 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)
9574 f = -DotProduct(r_refdef.view.forward, n);
9576 f = f * 0.85 + 0.15; // work around so stuff won't get black
9577 f *= r_refdef.lightmapintensity;
9578 Vector4Set(c, f, f, f, 1);
9582 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9584 RSurf_DrawBatch_GL11_ApplyFakeLight();
9585 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9586 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9587 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9588 GL_Color(r, g, b, a);
9592 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9600 vec3_t ambientcolor;
9601 vec3_t diffusecolor;
9605 VectorCopy(rsurface.modellight_lightdir, lightdir);
9606 f = 0.5f * r_refdef.lightmapintensity;
9607 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9608 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9609 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9610 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9611 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9612 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9614 if (VectorLength2(diffusecolor) > 0)
9616 // q3-style directional shading
9617 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9618 rsurface.passcolor4f_vertexbuffer = 0;
9619 rsurface.passcolor4f_bufferoffset = 0;
9620 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)
9622 if ((f = DotProduct(n, lightdir)) > 0)
9623 VectorMA(ambientcolor, f, diffusecolor, c);
9625 VectorCopy(ambientcolor, c);
9632 *applycolor = false;
9636 *r = ambientcolor[0];
9637 *g = ambientcolor[1];
9638 *b = ambientcolor[2];
9639 rsurface.passcolor4f = NULL;
9640 rsurface.passcolor4f_vertexbuffer = 0;
9641 rsurface.passcolor4f_bufferoffset = 0;
9645 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9647 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9648 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9649 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9650 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9651 GL_Color(r, g, b, a);
9655 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9663 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9664 rsurface.passcolor4f_vertexbuffer = 0;
9665 rsurface.passcolor4f_bufferoffset = 0;
9667 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9669 f = 1 - RSurf_FogVertex(v);
9677 void RSurf_SetupDepthAndCulling(void)
9679 // submodels are biased to avoid z-fighting with world surfaces that they
9680 // may be exactly overlapping (avoids z-fighting artifacts on certain
9681 // doors and things in Quake maps)
9682 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9683 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9684 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9685 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9688 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9690 // transparent sky would be ridiculous
9691 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9693 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9694 skyrenderlater = true;
9695 RSurf_SetupDepthAndCulling();
9697 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9698 // skymasking on them, and Quake3 never did sky masking (unlike
9699 // software Quake and software Quake2), so disable the sky masking
9700 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9701 // and skymasking also looks very bad when noclipping outside the
9702 // level, so don't use it then either.
9703 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9705 R_Mesh_ResetTextureState();
9706 if (skyrendermasked)
9708 R_SetupShader_DepthOrShadow(false);
9709 // depth-only (masking)
9710 GL_ColorMask(0,0,0,0);
9711 // just to make sure that braindead drivers don't draw
9712 // anything despite that colormask...
9713 GL_BlendFunc(GL_ZERO, GL_ONE);
9714 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9715 if (rsurface.batchvertex3fbuffer)
9716 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9718 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9722 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9724 GL_BlendFunc(GL_ONE, GL_ZERO);
9725 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9726 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9727 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9730 if (skyrendermasked)
9731 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9733 R_Mesh_ResetTextureState();
9734 GL_Color(1, 1, 1, 1);
9737 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9738 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9739 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9741 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9745 // render screenspace normalmap to texture
9747 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9751 // bind lightmap texture
9753 // water/refraction/reflection/camera surfaces have to be handled specially
9754 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9756 int start, end, startplaneindex;
9757 for (start = 0;start < texturenumsurfaces;start = end)
9759 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9760 if(startplaneindex < 0)
9762 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9763 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9767 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9769 // now that we have a batch using the same planeindex, render it
9770 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9772 // render water or distortion background
9774 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);
9776 // blend surface on top
9777 GL_DepthMask(false);
9778 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9781 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9783 // render surface with reflection texture as input
9784 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9785 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);
9792 // render surface batch normally
9793 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9794 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);
9798 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9800 // OpenGL 1.3 path - anything not completely ancient
9801 qboolean applycolor;
9804 const texturelayer_t *layer;
9805 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);
9806 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9808 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9811 int layertexrgbscale;
9812 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9814 if (layerindex == 0)
9818 GL_AlphaTest(false);
9819 GL_DepthFunc(GL_EQUAL);
9822 GL_DepthMask(layer->depthmask && writedepth);
9823 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9824 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9826 layertexrgbscale = 4;
9827 VectorScale(layer->color, 0.25f, layercolor);
9829 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9831 layertexrgbscale = 2;
9832 VectorScale(layer->color, 0.5f, layercolor);
9836 layertexrgbscale = 1;
9837 VectorScale(layer->color, 1.0f, layercolor);
9839 layercolor[3] = layer->color[3];
9840 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9841 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9842 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9843 switch (layer->type)
9845 case TEXTURELAYERTYPE_LITTEXTURE:
9846 // single-pass lightmapped texture with 2x rgbscale
9847 R_Mesh_TexBind(0, r_texture_white);
9848 R_Mesh_TexMatrix(0, NULL);
9849 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9850 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9851 R_Mesh_TexBind(1, layer->texture);
9852 R_Mesh_TexMatrix(1, &layer->texmatrix);
9853 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9854 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9855 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9856 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9857 else if (FAKELIGHT_ENABLED)
9858 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9859 else if (rsurface.uselightmaptexture)
9860 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9862 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9864 case TEXTURELAYERTYPE_TEXTURE:
9865 // singletexture unlit texture with transparency support
9866 R_Mesh_TexBind(0, layer->texture);
9867 R_Mesh_TexMatrix(0, &layer->texmatrix);
9868 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9869 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9870 R_Mesh_TexBind(1, 0);
9871 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9872 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9874 case TEXTURELAYERTYPE_FOG:
9875 // singletexture fogging
9878 R_Mesh_TexBind(0, layer->texture);
9879 R_Mesh_TexMatrix(0, &layer->texmatrix);
9880 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9881 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9885 R_Mesh_TexBind(0, 0);
9886 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9888 R_Mesh_TexBind(1, 0);
9889 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9890 // generate a color array for the fog pass
9891 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9892 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9896 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9899 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9901 GL_DepthFunc(GL_LEQUAL);
9902 GL_AlphaTest(false);
9906 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9908 // OpenGL 1.1 - crusty old voodoo path
9911 const texturelayer_t *layer;
9912 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);
9913 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9915 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9917 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9919 if (layerindex == 0)
9923 GL_AlphaTest(false);
9924 GL_DepthFunc(GL_EQUAL);
9927 GL_DepthMask(layer->depthmask && writedepth);
9928 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9929 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9930 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9931 switch (layer->type)
9933 case TEXTURELAYERTYPE_LITTEXTURE:
9934 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9936 // two-pass lit texture with 2x rgbscale
9937 // first the lightmap pass
9938 R_Mesh_TexBind(0, r_texture_white);
9939 R_Mesh_TexMatrix(0, NULL);
9940 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9941 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9942 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9943 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9944 else if (FAKELIGHT_ENABLED)
9945 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9946 else if (rsurface.uselightmaptexture)
9947 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9949 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9950 // then apply the texture to it
9951 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9952 R_Mesh_TexBind(0, layer->texture);
9953 R_Mesh_TexMatrix(0, &layer->texmatrix);
9954 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9955 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9956 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);
9960 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9961 R_Mesh_TexBind(0, layer->texture);
9962 R_Mesh_TexMatrix(0, &layer->texmatrix);
9963 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9964 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9965 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9966 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);
9968 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);
9971 case TEXTURELAYERTYPE_TEXTURE:
9972 // singletexture unlit texture with transparency support
9973 R_Mesh_TexBind(0, layer->texture);
9974 R_Mesh_TexMatrix(0, &layer->texmatrix);
9975 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9976 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9977 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);
9979 case TEXTURELAYERTYPE_FOG:
9980 // singletexture fogging
9983 R_Mesh_TexBind(0, layer->texture);
9984 R_Mesh_TexMatrix(0, &layer->texmatrix);
9985 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9986 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9990 R_Mesh_TexBind(0, 0);
9991 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9993 // generate a color array for the fog pass
9994 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9995 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9999 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10002 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10004 GL_DepthFunc(GL_LEQUAL);
10005 GL_AlphaTest(false);
10009 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10013 r_vertexgeneric_t *batchvertex;
10016 // R_Mesh_ResetTextureState();
10017 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10019 if(rsurface.texture && rsurface.texture->currentskinframe)
10021 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10022 c[3] *= rsurface.texture->currentalpha;
10032 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10034 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10035 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10036 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10039 // brighten it up (as texture value 127 means "unlit")
10040 c[0] *= 2 * r_refdef.view.colorscale;
10041 c[1] *= 2 * r_refdef.view.colorscale;
10042 c[2] *= 2 * r_refdef.view.colorscale;
10044 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10045 c[3] *= r_wateralpha.value;
10047 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10049 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10050 GL_DepthMask(false);
10052 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10054 GL_BlendFunc(GL_ONE, GL_ONE);
10055 GL_DepthMask(false);
10057 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10059 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10060 GL_DepthMask(false);
10062 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10064 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10065 GL_DepthMask(false);
10069 GL_BlendFunc(GL_ONE, GL_ZERO);
10070 GL_DepthMask(writedepth);
10073 if (r_showsurfaces.integer == 3)
10075 rsurface.passcolor4f = NULL;
10077 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10079 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10081 rsurface.passcolor4f = NULL;
10082 rsurface.passcolor4f_vertexbuffer = 0;
10083 rsurface.passcolor4f_bufferoffset = 0;
10085 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10087 qboolean applycolor = true;
10090 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10092 r_refdef.lightmapintensity = 1;
10093 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10094 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10096 else if (FAKELIGHT_ENABLED)
10098 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10100 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10101 RSurf_DrawBatch_GL11_ApplyFakeLight();
10102 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10106 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10108 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10109 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10110 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10113 if(!rsurface.passcolor4f)
10114 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10116 RSurf_DrawBatch_GL11_ApplyAmbient();
10117 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10118 if(r_refdef.fogenabled)
10119 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10120 RSurf_DrawBatch_GL11_ClampColor();
10122 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10123 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10126 else if (!r_refdef.view.showdebug)
10128 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10129 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10130 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10132 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10133 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10135 R_Mesh_PrepareVertices_Generic_Unlock();
10138 else if (r_showsurfaces.integer == 4)
10140 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10141 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10142 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10144 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10145 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10146 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10148 R_Mesh_PrepareVertices_Generic_Unlock();
10151 else if (r_showsurfaces.integer == 2)
10154 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10155 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10156 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10158 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10159 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10160 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10161 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10162 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10163 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10164 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10166 R_Mesh_PrepareVertices_Generic_Unlock();
10167 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10171 int texturesurfaceindex;
10173 const msurface_t *surface;
10174 float surfacecolor4f[4];
10175 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10176 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10178 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10180 surface = texturesurfacelist[texturesurfaceindex];
10181 k = (int)(((size_t)surface) / sizeof(msurface_t));
10182 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10183 for (j = 0;j < surface->num_vertices;j++)
10185 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10186 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10190 R_Mesh_PrepareVertices_Generic_Unlock();
10195 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10198 RSurf_SetupDepthAndCulling();
10199 if (r_showsurfaces.integer)
10201 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10204 switch (vid.renderpath)
10206 case RENDERPATH_GL20:
10207 case RENDERPATH_D3D9:
10208 case RENDERPATH_D3D10:
10209 case RENDERPATH_D3D11:
10210 case RENDERPATH_SOFT:
10211 case RENDERPATH_GLES2:
10212 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10214 case RENDERPATH_GL13:
10215 case RENDERPATH_GLES1:
10216 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10218 case RENDERPATH_GL11:
10219 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10225 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10228 RSurf_SetupDepthAndCulling();
10229 if (r_showsurfaces.integer)
10231 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10234 switch (vid.renderpath)
10236 case RENDERPATH_GL20:
10237 case RENDERPATH_D3D9:
10238 case RENDERPATH_D3D10:
10239 case RENDERPATH_D3D11:
10240 case RENDERPATH_SOFT:
10241 case RENDERPATH_GLES2:
10242 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10244 case RENDERPATH_GL13:
10245 case RENDERPATH_GLES1:
10246 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10248 case RENDERPATH_GL11:
10249 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10255 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10258 int texturenumsurfaces, endsurface;
10259 texture_t *texture;
10260 const msurface_t *surface;
10261 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10263 // if the model is static it doesn't matter what value we give for
10264 // wantnormals and wanttangents, so this logic uses only rules applicable
10265 // to a model, knowing that they are meaningless otherwise
10266 if (ent == r_refdef.scene.worldentity)
10267 RSurf_ActiveWorldEntity();
10268 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10269 RSurf_ActiveModelEntity(ent, false, false, false);
10272 switch (vid.renderpath)
10274 case RENDERPATH_GL20:
10275 case RENDERPATH_D3D9:
10276 case RENDERPATH_D3D10:
10277 case RENDERPATH_D3D11:
10278 case RENDERPATH_SOFT:
10279 case RENDERPATH_GLES2:
10280 RSurf_ActiveModelEntity(ent, true, true, false);
10282 case RENDERPATH_GL11:
10283 case RENDERPATH_GL13:
10284 case RENDERPATH_GLES1:
10285 RSurf_ActiveModelEntity(ent, true, false, false);
10290 if (r_transparentdepthmasking.integer)
10292 qboolean setup = false;
10293 for (i = 0;i < numsurfaces;i = j)
10296 surface = rsurface.modelsurfaces + surfacelist[i];
10297 texture = surface->texture;
10298 rsurface.texture = R_GetCurrentTexture(texture);
10299 rsurface.lightmaptexture = NULL;
10300 rsurface.deluxemaptexture = NULL;
10301 rsurface.uselightmaptexture = false;
10302 // scan ahead until we find a different texture
10303 endsurface = min(i + 1024, numsurfaces);
10304 texturenumsurfaces = 0;
10305 texturesurfacelist[texturenumsurfaces++] = surface;
10306 for (;j < endsurface;j++)
10308 surface = rsurface.modelsurfaces + surfacelist[j];
10309 if (texture != surface->texture)
10311 texturesurfacelist[texturenumsurfaces++] = surface;
10313 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10315 // render the range of surfaces as depth
10319 GL_ColorMask(0,0,0,0);
10321 GL_DepthTest(true);
10322 GL_BlendFunc(GL_ONE, GL_ZERO);
10323 GL_DepthMask(true);
10324 // R_Mesh_ResetTextureState();
10325 R_SetupShader_DepthOrShadow(false);
10327 RSurf_SetupDepthAndCulling();
10328 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10329 if (rsurface.batchvertex3fbuffer)
10330 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10332 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10336 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10339 for (i = 0;i < numsurfaces;i = j)
10342 surface = rsurface.modelsurfaces + surfacelist[i];
10343 texture = surface->texture;
10344 rsurface.texture = R_GetCurrentTexture(texture);
10345 // scan ahead until we find a different texture
10346 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10347 texturenumsurfaces = 0;
10348 texturesurfacelist[texturenumsurfaces++] = surface;
10349 if(FAKELIGHT_ENABLED)
10351 rsurface.lightmaptexture = NULL;
10352 rsurface.deluxemaptexture = NULL;
10353 rsurface.uselightmaptexture = false;
10354 for (;j < endsurface;j++)
10356 surface = rsurface.modelsurfaces + surfacelist[j];
10357 if (texture != surface->texture)
10359 texturesurfacelist[texturenumsurfaces++] = surface;
10364 rsurface.lightmaptexture = surface->lightmaptexture;
10365 rsurface.deluxemaptexture = surface->deluxemaptexture;
10366 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10367 for (;j < endsurface;j++)
10369 surface = rsurface.modelsurfaces + surfacelist[j];
10370 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10372 texturesurfacelist[texturenumsurfaces++] = surface;
10375 // render the range of surfaces
10376 if (ent == r_refdef.scene.worldentity)
10377 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10379 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10381 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10384 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10386 // transparent surfaces get pushed off into the transparent queue
10387 int surfacelistindex;
10388 const msurface_t *surface;
10389 vec3_t tempcenter, center;
10390 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10392 surface = texturesurfacelist[surfacelistindex];
10393 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10394 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10395 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10396 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10397 if (queueentity->transparent_offset) // transparent offset
10399 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10400 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10401 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10403 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10407 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10409 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10411 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10413 RSurf_SetupDepthAndCulling();
10414 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10415 if (rsurface.batchvertex3fbuffer)
10416 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10418 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10422 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10424 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10427 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10430 if (!rsurface.texture->currentnumlayers)
10432 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10433 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10435 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10437 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10438 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10439 else if (!rsurface.texture->currentnumlayers)
10441 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10443 // in the deferred case, transparent surfaces were queued during prepass
10444 if (!r_shadow_usingdeferredprepass)
10445 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10449 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10450 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10455 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10458 texture_t *texture;
10459 R_FrameData_SetMark();
10460 // break the surface list down into batches by texture and use of lightmapping
10461 for (i = 0;i < numsurfaces;i = j)
10464 // texture is the base texture pointer, rsurface.texture is the
10465 // current frame/skin the texture is directing us to use (for example
10466 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10467 // use skin 1 instead)
10468 texture = surfacelist[i]->texture;
10469 rsurface.texture = R_GetCurrentTexture(texture);
10470 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10472 // if this texture is not the kind we want, skip ahead to the next one
10473 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10477 if(FAKELIGHT_ENABLED || depthonly || prepass)
10479 rsurface.lightmaptexture = NULL;
10480 rsurface.deluxemaptexture = NULL;
10481 rsurface.uselightmaptexture = false;
10482 // simply scan ahead until we find a different texture or lightmap state
10483 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10488 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10489 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10490 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10491 // simply scan ahead until we find a different texture or lightmap state
10492 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10495 // render the range of surfaces
10496 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10498 R_FrameData_ReturnToMark();
10501 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10505 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10508 if (!rsurface.texture->currentnumlayers)
10510 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10511 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10513 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10515 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10516 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10517 else if (!rsurface.texture->currentnumlayers)
10519 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10521 // in the deferred case, transparent surfaces were queued during prepass
10522 if (!r_shadow_usingdeferredprepass)
10523 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10527 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10528 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10533 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10536 texture_t *texture;
10537 R_FrameData_SetMark();
10538 // break the surface list down into batches by texture and use of lightmapping
10539 for (i = 0;i < numsurfaces;i = j)
10542 // texture is the base texture pointer, rsurface.texture is the
10543 // current frame/skin the texture is directing us to use (for example
10544 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10545 // use skin 1 instead)
10546 texture = surfacelist[i]->texture;
10547 rsurface.texture = R_GetCurrentTexture(texture);
10548 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10550 // if this texture is not the kind we want, skip ahead to the next one
10551 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10555 if(FAKELIGHT_ENABLED || depthonly || prepass)
10557 rsurface.lightmaptexture = NULL;
10558 rsurface.deluxemaptexture = NULL;
10559 rsurface.uselightmaptexture = false;
10560 // simply scan ahead until we find a different texture or lightmap state
10561 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10566 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10567 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10568 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10569 // simply scan ahead until we find a different texture or lightmap state
10570 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10573 // render the range of surfaces
10574 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10576 R_FrameData_ReturnToMark();
10579 float locboxvertex3f[6*4*3] =
10581 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10582 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10583 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10584 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10585 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10586 1,0,0, 0,0,0, 0,1,0, 1,1,0
10589 unsigned short locboxelements[6*2*3] =
10594 12,13,14, 12,14,15,
10595 16,17,18, 16,18,19,
10599 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10602 cl_locnode_t *loc = (cl_locnode_t *)ent;
10604 float vertex3f[6*4*3];
10606 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10607 GL_DepthMask(false);
10608 GL_DepthRange(0, 1);
10609 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10610 GL_DepthTest(true);
10611 GL_CullFace(GL_NONE);
10612 R_EntityMatrix(&identitymatrix);
10614 // R_Mesh_ResetTextureState();
10616 i = surfacelist[0];
10617 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10618 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10619 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10620 surfacelist[0] < 0 ? 0.5f : 0.125f);
10622 if (VectorCompare(loc->mins, loc->maxs))
10624 VectorSet(size, 2, 2, 2);
10625 VectorMA(loc->mins, -0.5f, size, mins);
10629 VectorCopy(loc->mins, mins);
10630 VectorSubtract(loc->maxs, loc->mins, size);
10633 for (i = 0;i < 6*4*3;)
10634 for (j = 0;j < 3;j++, i++)
10635 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10637 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10638 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10639 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10642 void R_DrawLocs(void)
10645 cl_locnode_t *loc, *nearestloc;
10647 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10648 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10650 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10651 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10655 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10657 if (decalsystem->decals)
10658 Mem_Free(decalsystem->decals);
10659 memset(decalsystem, 0, sizeof(*decalsystem));
10662 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)
10665 tridecal_t *decals;
10668 // expand or initialize the system
10669 if (decalsystem->maxdecals <= decalsystem->numdecals)
10671 decalsystem_t old = *decalsystem;
10672 qboolean useshortelements;
10673 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10674 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10675 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)));
10676 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10677 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10678 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10679 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10680 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10681 if (decalsystem->numdecals)
10682 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10684 Mem_Free(old.decals);
10685 for (i = 0;i < decalsystem->maxdecals*3;i++)
10686 decalsystem->element3i[i] = i;
10687 if (useshortelements)
10688 for (i = 0;i < decalsystem->maxdecals*3;i++)
10689 decalsystem->element3s[i] = i;
10692 // grab a decal and search for another free slot for the next one
10693 decals = decalsystem->decals;
10694 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10695 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10697 decalsystem->freedecal = i;
10698 if (decalsystem->numdecals <= i)
10699 decalsystem->numdecals = i + 1;
10701 // initialize the decal
10703 decal->triangleindex = triangleindex;
10704 decal->surfaceindex = surfaceindex;
10705 decal->decalsequence = decalsequence;
10706 decal->color4f[0][0] = c0[0];
10707 decal->color4f[0][1] = c0[1];
10708 decal->color4f[0][2] = c0[2];
10709 decal->color4f[0][3] = 1;
10710 decal->color4f[1][0] = c1[0];
10711 decal->color4f[1][1] = c1[1];
10712 decal->color4f[1][2] = c1[2];
10713 decal->color4f[1][3] = 1;
10714 decal->color4f[2][0] = c2[0];
10715 decal->color4f[2][1] = c2[1];
10716 decal->color4f[2][2] = c2[2];
10717 decal->color4f[2][3] = 1;
10718 decal->vertex3f[0][0] = v0[0];
10719 decal->vertex3f[0][1] = v0[1];
10720 decal->vertex3f[0][2] = v0[2];
10721 decal->vertex3f[1][0] = v1[0];
10722 decal->vertex3f[1][1] = v1[1];
10723 decal->vertex3f[1][2] = v1[2];
10724 decal->vertex3f[2][0] = v2[0];
10725 decal->vertex3f[2][1] = v2[1];
10726 decal->vertex3f[2][2] = v2[2];
10727 decal->texcoord2f[0][0] = t0[0];
10728 decal->texcoord2f[0][1] = t0[1];
10729 decal->texcoord2f[1][0] = t1[0];
10730 decal->texcoord2f[1][1] = t1[1];
10731 decal->texcoord2f[2][0] = t2[0];
10732 decal->texcoord2f[2][1] = t2[1];
10733 TriangleNormal(v0, v1, v2, decal->plane);
10734 VectorNormalize(decal->plane);
10735 decal->plane[3] = DotProduct(v0, decal->plane);
10738 extern cvar_t cl_decals_bias;
10739 extern cvar_t cl_decals_models;
10740 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10741 // baseparms, parms, temps
10742 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)
10747 const float *vertex3f;
10748 const float *normal3f;
10750 float points[2][9][3];
10757 e = rsurface.modelelement3i + 3*triangleindex;
10759 vertex3f = rsurface.modelvertex3f;
10760 normal3f = rsurface.modelnormal3f;
10764 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10766 index = 3*e[cornerindex];
10767 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10772 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10774 index = 3*e[cornerindex];
10775 VectorCopy(vertex3f + index, v[cornerindex]);
10780 //TriangleNormal(v[0], v[1], v[2], normal);
10781 //if (DotProduct(normal, localnormal) < 0.0f)
10783 // clip by each of the box planes formed from the projection matrix
10784 // if anything survives, we emit the decal
10785 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]);
10788 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]);
10791 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]);
10794 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]);
10797 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]);
10800 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]);
10803 // some part of the triangle survived, so we have to accept it...
10806 // dynamic always uses the original triangle
10808 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10810 index = 3*e[cornerindex];
10811 VectorCopy(vertex3f + index, v[cornerindex]);
10814 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10816 // convert vertex positions to texcoords
10817 Matrix4x4_Transform(projection, v[cornerindex], temp);
10818 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10819 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10820 // calculate distance fade from the projection origin
10821 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10822 f = bound(0.0f, f, 1.0f);
10823 c[cornerindex][0] = r * f;
10824 c[cornerindex][1] = g * f;
10825 c[cornerindex][2] = b * f;
10826 c[cornerindex][3] = 1.0f;
10827 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10830 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);
10832 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10833 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);
10835 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)
10837 matrix4x4_t projection;
10838 decalsystem_t *decalsystem;
10841 const msurface_t *surface;
10842 const msurface_t *surfaces;
10843 const int *surfacelist;
10844 const texture_t *texture;
10846 int numsurfacelist;
10847 int surfacelistindex;
10850 float localorigin[3];
10851 float localnormal[3];
10852 float localmins[3];
10853 float localmaxs[3];
10856 float planes[6][4];
10859 int bih_triangles_count;
10860 int bih_triangles[256];
10861 int bih_surfaces[256];
10863 decalsystem = &ent->decalsystem;
10864 model = ent->model;
10865 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10867 R_DecalSystem_Reset(&ent->decalsystem);
10871 if (!model->brush.data_leafs && !cl_decals_models.integer)
10873 if (decalsystem->model)
10874 R_DecalSystem_Reset(decalsystem);
10878 if (decalsystem->model != model)
10879 R_DecalSystem_Reset(decalsystem);
10880 decalsystem->model = model;
10882 RSurf_ActiveModelEntity(ent, true, false, false);
10884 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10885 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10886 VectorNormalize(localnormal);
10887 localsize = worldsize*rsurface.inversematrixscale;
10888 localmins[0] = localorigin[0] - localsize;
10889 localmins[1] = localorigin[1] - localsize;
10890 localmins[2] = localorigin[2] - localsize;
10891 localmaxs[0] = localorigin[0] + localsize;
10892 localmaxs[1] = localorigin[1] + localsize;
10893 localmaxs[2] = localorigin[2] + localsize;
10895 //VectorCopy(localnormal, planes[4]);
10896 //VectorVectors(planes[4], planes[2], planes[0]);
10897 AnglesFromVectors(angles, localnormal, NULL, false);
10898 AngleVectors(angles, planes[0], planes[2], planes[4]);
10899 VectorNegate(planes[0], planes[1]);
10900 VectorNegate(planes[2], planes[3]);
10901 VectorNegate(planes[4], planes[5]);
10902 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10903 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10904 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10905 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10906 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10907 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10912 matrix4x4_t forwardprojection;
10913 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10914 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10919 float projectionvector[4][3];
10920 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10921 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10922 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10923 projectionvector[0][0] = planes[0][0] * ilocalsize;
10924 projectionvector[0][1] = planes[1][0] * ilocalsize;
10925 projectionvector[0][2] = planes[2][0] * ilocalsize;
10926 projectionvector[1][0] = planes[0][1] * ilocalsize;
10927 projectionvector[1][1] = planes[1][1] * ilocalsize;
10928 projectionvector[1][2] = planes[2][1] * ilocalsize;
10929 projectionvector[2][0] = planes[0][2] * ilocalsize;
10930 projectionvector[2][1] = planes[1][2] * ilocalsize;
10931 projectionvector[2][2] = planes[2][2] * ilocalsize;
10932 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10933 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10934 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10935 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10939 dynamic = model->surfmesh.isanimated;
10940 numsurfacelist = model->nummodelsurfaces;
10941 surfacelist = model->sortedmodelsurfaces;
10942 surfaces = model->data_surfaces;
10945 bih_triangles_count = -1;
10948 if(model->render_bih.numleafs)
10949 bih = &model->render_bih;
10950 else if(model->collision_bih.numleafs)
10951 bih = &model->collision_bih;
10954 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10955 if(bih_triangles_count == 0)
10957 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10959 if(bih_triangles_count > 0)
10961 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10963 surfaceindex = bih_surfaces[triangleindex];
10964 surface = surfaces + surfaceindex;
10965 texture = surface->texture;
10966 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10968 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10970 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10975 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10977 surfaceindex = surfacelist[surfacelistindex];
10978 surface = surfaces + surfaceindex;
10979 // check cull box first because it rejects more than any other check
10980 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10982 // skip transparent surfaces
10983 texture = surface->texture;
10984 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10986 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10988 numtriangles = surface->num_triangles;
10989 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10990 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10995 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10996 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)
10998 int renderentityindex;
10999 float worldmins[3];
11000 float worldmaxs[3];
11001 entity_render_t *ent;
11003 if (!cl_decals_newsystem.integer)
11006 worldmins[0] = worldorigin[0] - worldsize;
11007 worldmins[1] = worldorigin[1] - worldsize;
11008 worldmins[2] = worldorigin[2] - worldsize;
11009 worldmaxs[0] = worldorigin[0] + worldsize;
11010 worldmaxs[1] = worldorigin[1] + worldsize;
11011 worldmaxs[2] = worldorigin[2] + worldsize;
11013 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11015 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11017 ent = r_refdef.scene.entities[renderentityindex];
11018 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11021 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11025 typedef struct r_decalsystem_splatqueue_s
11027 vec3_t worldorigin;
11028 vec3_t worldnormal;
11034 r_decalsystem_splatqueue_t;
11036 int r_decalsystem_numqueued = 0;
11037 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11039 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)
11041 r_decalsystem_splatqueue_t *queue;
11043 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11046 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11047 VectorCopy(worldorigin, queue->worldorigin);
11048 VectorCopy(worldnormal, queue->worldnormal);
11049 Vector4Set(queue->color, r, g, b, a);
11050 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11051 queue->worldsize = worldsize;
11052 queue->decalsequence = cl.decalsequence++;
11055 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11058 r_decalsystem_splatqueue_t *queue;
11060 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11061 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);
11062 r_decalsystem_numqueued = 0;
11065 extern cvar_t cl_decals_max;
11066 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11069 decalsystem_t *decalsystem = &ent->decalsystem;
11076 if (!decalsystem->numdecals)
11079 if (r_showsurfaces.integer)
11082 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11084 R_DecalSystem_Reset(decalsystem);
11088 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11089 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11091 if (decalsystem->lastupdatetime)
11092 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11095 decalsystem->lastupdatetime = r_refdef.scene.time;
11096 decal = decalsystem->decals;
11097 numdecals = decalsystem->numdecals;
11099 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11101 if (decal->color4f[0][3])
11103 decal->lived += frametime;
11104 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11106 memset(decal, 0, sizeof(*decal));
11107 if (decalsystem->freedecal > i)
11108 decalsystem->freedecal = i;
11112 decal = decalsystem->decals;
11113 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11116 // collapse the array by shuffling the tail decals into the gaps
11119 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11120 decalsystem->freedecal++;
11121 if (decalsystem->freedecal == numdecals)
11123 decal[decalsystem->freedecal] = decal[--numdecals];
11126 decalsystem->numdecals = numdecals;
11128 if (numdecals <= 0)
11130 // if there are no decals left, reset decalsystem
11131 R_DecalSystem_Reset(decalsystem);
11135 extern skinframe_t *decalskinframe;
11136 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11139 decalsystem_t *decalsystem = &ent->decalsystem;
11148 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11151 numdecals = decalsystem->numdecals;
11155 if (r_showsurfaces.integer)
11158 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11160 R_DecalSystem_Reset(decalsystem);
11164 // if the model is static it doesn't matter what value we give for
11165 // wantnormals and wanttangents, so this logic uses only rules applicable
11166 // to a model, knowing that they are meaningless otherwise
11167 if (ent == r_refdef.scene.worldentity)
11168 RSurf_ActiveWorldEntity();
11170 RSurf_ActiveModelEntity(ent, false, false, false);
11172 decalsystem->lastupdatetime = r_refdef.scene.time;
11173 decal = decalsystem->decals;
11175 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11177 // update vertex positions for animated models
11178 v3f = decalsystem->vertex3f;
11179 c4f = decalsystem->color4f;
11180 t2f = decalsystem->texcoord2f;
11181 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11183 if (!decal->color4f[0][3])
11186 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11190 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11193 // update color values for fading decals
11194 if (decal->lived >= cl_decals_time.value)
11195 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11199 c4f[ 0] = decal->color4f[0][0] * alpha;
11200 c4f[ 1] = decal->color4f[0][1] * alpha;
11201 c4f[ 2] = decal->color4f[0][2] * alpha;
11203 c4f[ 4] = decal->color4f[1][0] * alpha;
11204 c4f[ 5] = decal->color4f[1][1] * alpha;
11205 c4f[ 6] = decal->color4f[1][2] * alpha;
11207 c4f[ 8] = decal->color4f[2][0] * alpha;
11208 c4f[ 9] = decal->color4f[2][1] * alpha;
11209 c4f[10] = decal->color4f[2][2] * alpha;
11212 t2f[0] = decal->texcoord2f[0][0];
11213 t2f[1] = decal->texcoord2f[0][1];
11214 t2f[2] = decal->texcoord2f[1][0];
11215 t2f[3] = decal->texcoord2f[1][1];
11216 t2f[4] = decal->texcoord2f[2][0];
11217 t2f[5] = decal->texcoord2f[2][1];
11219 // update vertex positions for animated models
11220 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11222 e = rsurface.modelelement3i + 3*decal->triangleindex;
11223 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11224 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11225 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11229 VectorCopy(decal->vertex3f[0], v3f);
11230 VectorCopy(decal->vertex3f[1], v3f + 3);
11231 VectorCopy(decal->vertex3f[2], v3f + 6);
11234 if (r_refdef.fogenabled)
11236 alpha = RSurf_FogVertex(v3f);
11237 VectorScale(c4f, alpha, c4f);
11238 alpha = RSurf_FogVertex(v3f + 3);
11239 VectorScale(c4f + 4, alpha, c4f + 4);
11240 alpha = RSurf_FogVertex(v3f + 6);
11241 VectorScale(c4f + 8, alpha, c4f + 8);
11252 r_refdef.stats.drawndecals += numtris;
11254 // now render the decals all at once
11255 // (this assumes they all use one particle font texture!)
11256 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);
11257 // R_Mesh_ResetTextureState();
11258 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11259 GL_DepthMask(false);
11260 GL_DepthRange(0, 1);
11261 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11262 GL_DepthTest(true);
11263 GL_CullFace(GL_NONE);
11264 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11265 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11266 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11270 static void R_DrawModelDecals(void)
11274 // fade faster when there are too many decals
11275 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11276 for (i = 0;i < r_refdef.scene.numentities;i++)
11277 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11279 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11280 for (i = 0;i < r_refdef.scene.numentities;i++)
11281 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11282 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11284 R_DecalSystem_ApplySplatEntitiesQueue();
11286 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11287 for (i = 0;i < r_refdef.scene.numentities;i++)
11288 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11290 r_refdef.stats.totaldecals += numdecals;
11292 if (r_showsurfaces.integer)
11295 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11297 for (i = 0;i < r_refdef.scene.numentities;i++)
11299 if (!r_refdef.viewcache.entityvisible[i])
11301 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11302 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11306 extern cvar_t mod_collision_bih;
11307 void R_DrawDebugModel(void)
11309 entity_render_t *ent = rsurface.entity;
11310 int i, j, k, l, flagsmask;
11311 const msurface_t *surface;
11312 dp_model_t *model = ent->model;
11315 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11318 if (r_showoverdraw.value > 0)
11320 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11321 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11322 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11323 GL_DepthTest(false);
11324 GL_DepthMask(false);
11325 GL_DepthRange(0, 1);
11326 GL_BlendFunc(GL_ONE, GL_ONE);
11327 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11329 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11331 rsurface.texture = R_GetCurrentTexture(surface->texture);
11332 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11334 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11335 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11336 if (!rsurface.texture->currentlayers->depthmask)
11337 GL_Color(c, 0, 0, 1.0f);
11338 else if (ent == r_refdef.scene.worldentity)
11339 GL_Color(c, c, c, 1.0f);
11341 GL_Color(0, c, 0, 1.0f);
11342 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11346 rsurface.texture = NULL;
11349 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11351 // R_Mesh_ResetTextureState();
11352 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11353 GL_DepthRange(0, 1);
11354 GL_DepthTest(!r_showdisabledepthtest.integer);
11355 GL_DepthMask(false);
11356 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11358 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11362 qboolean cullbox = ent == r_refdef.scene.worldentity;
11363 const q3mbrush_t *brush;
11364 const bih_t *bih = &model->collision_bih;
11365 const bih_leaf_t *bihleaf;
11366 float vertex3f[3][3];
11367 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11369 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11371 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11373 switch (bihleaf->type)
11376 brush = model->brush.data_brushes + bihleaf->itemindex;
11377 if (brush->colbrushf && brush->colbrushf->numtriangles)
11379 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);
11380 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11381 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11384 case BIH_COLLISIONTRIANGLE:
11385 triangleindex = bihleaf->itemindex;
11386 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11387 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11388 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11389 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);
11390 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11391 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11393 case BIH_RENDERTRIANGLE:
11394 triangleindex = bihleaf->itemindex;
11395 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11396 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11397 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11398 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);
11399 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11400 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11406 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11409 if (r_showtris.integer && qglPolygonMode)
11411 if (r_showdisabledepthtest.integer)
11413 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11414 GL_DepthMask(false);
11418 GL_BlendFunc(GL_ONE, GL_ZERO);
11419 GL_DepthMask(true);
11421 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11422 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11424 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11426 rsurface.texture = R_GetCurrentTexture(surface->texture);
11427 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11429 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11430 if (!rsurface.texture->currentlayers->depthmask)
11431 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11432 else if (ent == r_refdef.scene.worldentity)
11433 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11435 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11436 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11440 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11441 rsurface.texture = NULL;
11444 if (r_shownormals.value != 0 && qglBegin)
11446 if (r_showdisabledepthtest.integer)
11448 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11449 GL_DepthMask(false);
11453 GL_BlendFunc(GL_ONE, GL_ZERO);
11454 GL_DepthMask(true);
11456 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11458 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11460 rsurface.texture = R_GetCurrentTexture(surface->texture);
11461 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11463 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11464 qglBegin(GL_LINES);
11465 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11467 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11469 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11470 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11471 qglVertex3f(v[0], v[1], v[2]);
11472 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11473 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11474 qglVertex3f(v[0], v[1], v[2]);
11477 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11479 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11481 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11482 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11483 qglVertex3f(v[0], v[1], v[2]);
11484 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11485 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11486 qglVertex3f(v[0], v[1], v[2]);
11489 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11491 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11493 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11494 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11495 qglVertex3f(v[0], v[1], v[2]);
11496 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11497 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11498 qglVertex3f(v[0], v[1], v[2]);
11501 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11503 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11505 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11506 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11507 qglVertex3f(v[0], v[1], v[2]);
11508 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11509 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11510 qglVertex3f(v[0], v[1], v[2]);
11517 rsurface.texture = NULL;
11522 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11523 int r_maxsurfacelist = 0;
11524 const msurface_t **r_surfacelist = NULL;
11525 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11527 int i, j, endj, flagsmask;
11528 dp_model_t *model = r_refdef.scene.worldmodel;
11529 msurface_t *surfaces;
11530 unsigned char *update;
11531 int numsurfacelist = 0;
11535 if (r_maxsurfacelist < model->num_surfaces)
11537 r_maxsurfacelist = model->num_surfaces;
11539 Mem_Free((msurface_t**)r_surfacelist);
11540 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11543 RSurf_ActiveWorldEntity();
11545 surfaces = model->data_surfaces;
11546 update = model->brushq1.lightmapupdateflags;
11548 // update light styles on this submodel
11549 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11551 model_brush_lightstyleinfo_t *style;
11552 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11554 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11556 int *list = style->surfacelist;
11557 style->value = r_refdef.scene.lightstylevalue[style->style];
11558 for (j = 0;j < style->numsurfaces;j++)
11559 update[list[j]] = true;
11564 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11568 R_DrawDebugModel();
11569 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11573 rsurface.lightmaptexture = NULL;
11574 rsurface.deluxemaptexture = NULL;
11575 rsurface.uselightmaptexture = false;
11576 rsurface.texture = NULL;
11577 rsurface.rtlight = NULL;
11578 numsurfacelist = 0;
11579 // add visible surfaces to draw list
11580 for (i = 0;i < model->nummodelsurfaces;i++)
11582 j = model->sortedmodelsurfaces[i];
11583 if (r_refdef.viewcache.world_surfacevisible[j])
11584 r_surfacelist[numsurfacelist++] = surfaces + j;
11586 // update lightmaps if needed
11587 if (model->brushq1.firstrender)
11589 model->brushq1.firstrender = false;
11590 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11592 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11596 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11597 if (r_refdef.viewcache.world_surfacevisible[j])
11599 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11601 // don't do anything if there were no surfaces
11602 if (!numsurfacelist)
11604 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11607 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11609 // add to stats if desired
11610 if (r_speeds.integer && !skysurfaces && !depthonly)
11612 r_refdef.stats.world_surfaces += numsurfacelist;
11613 for (j = 0;j < numsurfacelist;j++)
11614 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11617 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11620 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11622 int i, j, endj, flagsmask;
11623 dp_model_t *model = ent->model;
11624 msurface_t *surfaces;
11625 unsigned char *update;
11626 int numsurfacelist = 0;
11630 if (r_maxsurfacelist < model->num_surfaces)
11632 r_maxsurfacelist = model->num_surfaces;
11634 Mem_Free((msurface_t **)r_surfacelist);
11635 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11638 // if the model is static it doesn't matter what value we give for
11639 // wantnormals and wanttangents, so this logic uses only rules applicable
11640 // to a model, knowing that they are meaningless otherwise
11641 if (ent == r_refdef.scene.worldentity)
11642 RSurf_ActiveWorldEntity();
11643 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11644 RSurf_ActiveModelEntity(ent, false, false, false);
11646 RSurf_ActiveModelEntity(ent, true, true, true);
11647 else if (depthonly)
11649 switch (vid.renderpath)
11651 case RENDERPATH_GL20:
11652 case RENDERPATH_D3D9:
11653 case RENDERPATH_D3D10:
11654 case RENDERPATH_D3D11:
11655 case RENDERPATH_SOFT:
11656 case RENDERPATH_GLES2:
11657 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11659 case RENDERPATH_GL11:
11660 case RENDERPATH_GL13:
11661 case RENDERPATH_GLES1:
11662 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11668 switch (vid.renderpath)
11670 case RENDERPATH_GL20:
11671 case RENDERPATH_D3D9:
11672 case RENDERPATH_D3D10:
11673 case RENDERPATH_D3D11:
11674 case RENDERPATH_SOFT:
11675 case RENDERPATH_GLES2:
11676 RSurf_ActiveModelEntity(ent, true, true, false);
11678 case RENDERPATH_GL11:
11679 case RENDERPATH_GL13:
11680 case RENDERPATH_GLES1:
11681 RSurf_ActiveModelEntity(ent, true, false, false);
11686 surfaces = model->data_surfaces;
11687 update = model->brushq1.lightmapupdateflags;
11689 // update light styles
11690 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11692 model_brush_lightstyleinfo_t *style;
11693 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11695 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11697 int *list = style->surfacelist;
11698 style->value = r_refdef.scene.lightstylevalue[style->style];
11699 for (j = 0;j < style->numsurfaces;j++)
11700 update[list[j]] = true;
11705 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11709 R_DrawDebugModel();
11710 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11714 rsurface.lightmaptexture = NULL;
11715 rsurface.deluxemaptexture = NULL;
11716 rsurface.uselightmaptexture = false;
11717 rsurface.texture = NULL;
11718 rsurface.rtlight = NULL;
11719 numsurfacelist = 0;
11720 // add visible surfaces to draw list
11721 for (i = 0;i < model->nummodelsurfaces;i++)
11722 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11723 // don't do anything if there were no surfaces
11724 if (!numsurfacelist)
11726 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11729 // update lightmaps if needed
11733 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11738 R_BuildLightMap(ent, surfaces + j);
11743 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11745 R_BuildLightMap(ent, surfaces + j);
11746 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11748 // add to stats if desired
11749 if (r_speeds.integer && !skysurfaces && !depthonly)
11751 r_refdef.stats.entities_surfaces += numsurfacelist;
11752 for (j = 0;j < numsurfacelist;j++)
11753 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11756 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11759 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11761 static texture_t texture;
11762 static msurface_t surface;
11763 const msurface_t *surfacelist = &surface;
11765 // fake enough texture and surface state to render this geometry
11767 texture.update_lastrenderframe = -1; // regenerate this texture
11768 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11769 texture.currentskinframe = skinframe;
11770 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11771 texture.offsetmapping = OFFSETMAPPING_OFF;
11772 texture.offsetscale = 1;
11773 texture.specularscalemod = 1;
11774 texture.specularpowermod = 1;
11776 surface.texture = &texture;
11777 surface.num_triangles = numtriangles;
11778 surface.num_firsttriangle = firsttriangle;
11779 surface.num_vertices = numvertices;
11780 surface.num_firstvertex = firstvertex;
11783 rsurface.texture = R_GetCurrentTexture(surface.texture);
11784 rsurface.lightmaptexture = NULL;
11785 rsurface.deluxemaptexture = NULL;
11786 rsurface.uselightmaptexture = false;
11787 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11790 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)
11792 static msurface_t surface;
11793 const msurface_t *surfacelist = &surface;
11795 // fake enough texture and surface state to render this geometry
11796 surface.texture = texture;
11797 surface.num_triangles = numtriangles;
11798 surface.num_firsttriangle = firsttriangle;
11799 surface.num_vertices = numvertices;
11800 surface.num_firstvertex = firstvertex;
11803 rsurface.texture = R_GetCurrentTexture(surface.texture);
11804 rsurface.lightmaptexture = NULL;
11805 rsurface.deluxemaptexture = NULL;
11806 rsurface.uselightmaptexture = false;
11807 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);