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_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
103 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
106 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
107 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
110 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
111 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
112 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."};
113 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
114 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
115 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
116 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."};
117 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
118 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
119 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
120 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
121 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"};
122 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"};
123 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
124 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
126 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
127 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
128 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"};
129 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
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_drawviewmodel);
4218 Cvar_RegisterVariable(&r_drawexteriormodel);
4219 Cvar_RegisterVariable(&r_speeds);
4220 Cvar_RegisterVariable(&r_fullbrights);
4221 Cvar_RegisterVariable(&r_wateralpha);
4222 Cvar_RegisterVariable(&r_dynamic);
4223 Cvar_RegisterVariable(&r_fakelight);
4224 Cvar_RegisterVariable(&r_fakelight_intensity);
4225 Cvar_RegisterVariable(&r_fullbright);
4226 Cvar_RegisterVariable(&r_shadows);
4227 Cvar_RegisterVariable(&r_shadows_darken);
4228 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4229 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4230 Cvar_RegisterVariable(&r_shadows_throwdistance);
4231 Cvar_RegisterVariable(&r_shadows_throwdirection);
4232 Cvar_RegisterVariable(&r_shadows_focus);
4233 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4234 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4235 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4236 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4237 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4238 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4239 Cvar_RegisterVariable(&r_fog_exp2);
4240 Cvar_RegisterVariable(&r_fog_clear);
4241 Cvar_RegisterVariable(&r_drawfog);
4242 Cvar_RegisterVariable(&r_transparentdepthmasking);
4243 Cvar_RegisterVariable(&r_transparent_sortmindist);
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_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6538 if (gamemode == GAME_NEHAHRA)
6540 if (gl_fogenable.integer)
6542 r_refdef.oldgl_fogenable = true;
6543 r_refdef.fog_density = gl_fogdensity.value;
6544 r_refdef.fog_red = gl_fogred.value;
6545 r_refdef.fog_green = gl_foggreen.value;
6546 r_refdef.fog_blue = gl_fogblue.value;
6547 r_refdef.fog_alpha = 1;
6548 r_refdef.fog_start = 0;
6549 r_refdef.fog_end = gl_skyclip.value;
6550 r_refdef.fog_height = 1<<30;
6551 r_refdef.fog_fadedepth = 128;
6553 else if (r_refdef.oldgl_fogenable)
6555 r_refdef.oldgl_fogenable = false;
6556 r_refdef.fog_density = 0;
6557 r_refdef.fog_red = 0;
6558 r_refdef.fog_green = 0;
6559 r_refdef.fog_blue = 0;
6560 r_refdef.fog_alpha = 0;
6561 r_refdef.fog_start = 0;
6562 r_refdef.fog_end = 0;
6563 r_refdef.fog_height = 1<<30;
6564 r_refdef.fog_fadedepth = 128;
6569 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6570 r_refdef.fog_start = max(0, r_refdef.fog_start);
6571 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6573 if (r_refdef.fog_density && r_drawfog.integer)
6575 r_refdef.fogenabled = true;
6576 // this is the point where the fog reaches 0.9986 alpha, which we
6577 // consider a good enough cutoff point for the texture
6578 // (0.9986 * 256 == 255.6)
6579 if (r_fog_exp2.integer)
6580 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6582 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6583 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6584 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6585 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6586 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6587 R_BuildFogHeightTexture();
6588 // fog color was already set
6589 // update the fog texture
6590 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)
6591 R_BuildFogTexture();
6592 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6593 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6596 r_refdef.fogenabled = false;
6599 if (r_refdef.fog_density)
6601 r_refdef.fogcolor[0] = r_refdef.fog_red;
6602 r_refdef.fogcolor[1] = r_refdef.fog_green;
6603 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6605 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6606 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6607 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6608 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6612 VectorCopy(r_refdef.fogcolor, fogvec);
6613 // color.rgb *= ContrastBoost * SceneBrightness;
6614 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6615 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6616 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6617 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6622 void R_UpdateVariables(void)
6626 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6628 r_refdef.farclip = r_farclip_base.value;
6629 if (r_refdef.scene.worldmodel)
6630 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6631 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6633 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6634 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6635 r_refdef.polygonfactor = 0;
6636 r_refdef.polygonoffset = 0;
6637 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6638 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6640 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6641 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6642 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6643 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6644 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6645 if (FAKELIGHT_ENABLED)
6647 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6649 if (r_showsurfaces.integer)
6651 r_refdef.scene.rtworld = false;
6652 r_refdef.scene.rtworldshadows = false;
6653 r_refdef.scene.rtdlight = false;
6654 r_refdef.scene.rtdlightshadows = false;
6655 r_refdef.lightmapintensity = 0;
6658 switch(vid.renderpath)
6660 case RENDERPATH_GL20:
6661 case RENDERPATH_D3D9:
6662 case RENDERPATH_D3D10:
6663 case RENDERPATH_D3D11:
6664 case RENDERPATH_SOFT:
6665 case RENDERPATH_GLES2:
6666 if(v_glslgamma.integer && !vid_gammatables_trivial)
6668 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6670 // build GLSL gamma texture
6671 #define RAMPWIDTH 256
6672 unsigned short ramp[RAMPWIDTH * 3];
6673 unsigned char rampbgr[RAMPWIDTH][4];
6676 r_texture_gammaramps_serial = vid_gammatables_serial;
6678 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6679 for(i = 0; i < RAMPWIDTH; ++i)
6681 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6682 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6683 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6686 if (r_texture_gammaramps)
6688 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6692 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6698 // remove GLSL gamma texture
6701 case RENDERPATH_GL11:
6702 case RENDERPATH_GL13:
6703 case RENDERPATH_GLES1:
6708 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6709 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6715 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6716 if( scenetype != r_currentscenetype ) {
6717 // store the old scenetype
6718 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6719 r_currentscenetype = scenetype;
6720 // move in the new scene
6721 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6730 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6732 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6733 if( scenetype == r_currentscenetype ) {
6734 return &r_refdef.scene;
6736 return &r_scenes_store[ scenetype ];
6745 int dpsoftrast_test;
6746 extern void R_Shadow_UpdateBounceGridTexture(void);
6747 extern cvar_t r_shadow_bouncegrid;
6748 void R_RenderView(void)
6750 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6752 dpsoftrast_test = r_test.integer;
6754 if (r_timereport_active)
6755 R_TimeReport("start");
6756 r_textureframe++; // used only by R_GetCurrentTexture
6757 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6759 if(R_CompileShader_CheckStaticParms())
6762 if (!r_drawentities.integer)
6763 r_refdef.scene.numentities = 0;
6765 R_AnimCache_ClearCache();
6766 R_FrameData_NewFrame();
6768 /* adjust for stereo display */
6769 if(R_Stereo_Active())
6771 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);
6772 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6775 if (r_refdef.view.isoverlay)
6777 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6778 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6779 R_TimeReport("depthclear");
6781 r_refdef.view.showdebug = false;
6783 r_waterstate.enabled = false;
6784 r_waterstate.numwaterplanes = 0;
6788 r_refdef.view.matrix = originalmatrix;
6794 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6796 r_refdef.view.matrix = originalmatrix;
6797 return; //Host_Error ("R_RenderView: NULL worldmodel");
6800 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6802 R_RenderView_UpdateViewVectors();
6804 R_Shadow_UpdateWorldLightSelection();
6806 R_Bloom_StartFrame();
6807 R_Water_StartFrame();
6810 if (r_timereport_active)
6811 R_TimeReport("viewsetup");
6813 R_ResetViewRendering3D();
6815 if (r_refdef.view.clear || r_refdef.fogenabled)
6817 R_ClearScreen(r_refdef.fogenabled);
6818 if (r_timereport_active)
6819 R_TimeReport("viewclear");
6821 r_refdef.view.clear = true;
6823 // this produces a bloom texture to be used in R_BlendView() later
6824 if (r_bloomstate.hdr)
6826 R_HDR_RenderBloomTexture();
6827 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6828 r_textureframe++; // used only by R_GetCurrentTexture
6831 r_refdef.view.showdebug = true;
6834 if (r_timereport_active)
6835 R_TimeReport("visibility");
6837 R_Shadow_UpdateBounceGridTexture();
6838 if (r_timereport_active && r_shadow_bouncegrid.integer)
6839 R_TimeReport("bouncegrid");
6841 r_waterstate.numwaterplanes = 0;
6842 if (r_waterstate.enabled)
6843 R_RenderWaterPlanes();
6846 r_waterstate.numwaterplanes = 0;
6849 if (r_timereport_active)
6850 R_TimeReport("blendview");
6852 GL_Scissor(0, 0, vid.width, vid.height);
6853 GL_ScissorTest(false);
6855 r_refdef.view.matrix = originalmatrix;
6860 void R_RenderWaterPlanes(void)
6862 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6864 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6865 if (r_timereport_active)
6866 R_TimeReport("waterworld");
6869 // don't let sound skip if going slow
6870 if (r_refdef.scene.extraupdate)
6873 R_DrawModelsAddWaterPlanes();
6874 if (r_timereport_active)
6875 R_TimeReport("watermodels");
6877 if (r_waterstate.numwaterplanes)
6879 R_Water_ProcessPlanes();
6880 if (r_timereport_active)
6881 R_TimeReport("waterscenes");
6885 extern void R_DrawLightningBeams (void);
6886 extern void VM_CL_AddPolygonsToMeshQueue (void);
6887 extern void R_DrawPortals (void);
6888 extern cvar_t cl_locs_show;
6889 static void R_DrawLocs(void);
6890 static void R_DrawEntityBBoxes(void);
6891 static void R_DrawModelDecals(void);
6892 extern void R_DrawModelShadows(void);
6893 extern void R_DrawModelShadowMaps(void);
6894 extern cvar_t cl_decals_newsystem;
6895 extern qboolean r_shadow_usingdeferredprepass;
6896 void R_RenderScene(void)
6898 qboolean shadowmapping = false;
6900 if (r_timereport_active)
6901 R_TimeReport("beginscene");
6903 r_refdef.stats.renders++;
6907 // don't let sound skip if going slow
6908 if (r_refdef.scene.extraupdate)
6911 R_MeshQueue_BeginScene();
6915 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);
6917 if (r_timereport_active)
6918 R_TimeReport("skystartframe");
6920 if (cl.csqc_vidvars.drawworld)
6922 // don't let sound skip if going slow
6923 if (r_refdef.scene.extraupdate)
6926 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6928 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6929 if (r_timereport_active)
6930 R_TimeReport("worldsky");
6933 if (R_DrawBrushModelsSky() && r_timereport_active)
6934 R_TimeReport("bmodelsky");
6936 if (skyrendermasked && skyrenderlater)
6938 // we have to force off the water clipping plane while rendering sky
6942 if (r_timereport_active)
6943 R_TimeReport("sky");
6947 R_AnimCache_CacheVisibleEntities();
6948 if (r_timereport_active)
6949 R_TimeReport("animation");
6951 R_Shadow_PrepareLights();
6952 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6953 R_Shadow_PrepareModelShadows();
6954 if (r_timereport_active)
6955 R_TimeReport("preparelights");
6957 if (R_Shadow_ShadowMappingEnabled())
6958 shadowmapping = true;
6960 if (r_shadow_usingdeferredprepass)
6961 R_Shadow_DrawPrepass();
6963 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6965 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6966 if (r_timereport_active)
6967 R_TimeReport("worlddepth");
6969 if (r_depthfirst.integer >= 2)
6971 R_DrawModelsDepth();
6972 if (r_timereport_active)
6973 R_TimeReport("modeldepth");
6976 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6978 R_DrawModelShadowMaps();
6979 R_ResetViewRendering3D();
6980 // don't let sound skip if going slow
6981 if (r_refdef.scene.extraupdate)
6985 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6987 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6988 if (r_timereport_active)
6989 R_TimeReport("world");
6992 // don't let sound skip if going slow
6993 if (r_refdef.scene.extraupdate)
6997 if (r_timereport_active)
6998 R_TimeReport("models");
7000 // don't let sound skip if going slow
7001 if (r_refdef.scene.extraupdate)
7004 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7006 R_DrawModelShadows();
7007 R_ResetViewRendering3D();
7008 // don't let sound skip if going slow
7009 if (r_refdef.scene.extraupdate)
7013 if (!r_shadow_usingdeferredprepass)
7015 R_Shadow_DrawLights();
7016 if (r_timereport_active)
7017 R_TimeReport("rtlights");
7020 // don't let sound skip if going slow
7021 if (r_refdef.scene.extraupdate)
7024 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7026 R_DrawModelShadows();
7027 R_ResetViewRendering3D();
7028 // don't let sound skip if going slow
7029 if (r_refdef.scene.extraupdate)
7033 if (cl.csqc_vidvars.drawworld)
7035 if (cl_decals_newsystem.integer)
7037 R_DrawModelDecals();
7038 if (r_timereport_active)
7039 R_TimeReport("modeldecals");
7044 if (r_timereport_active)
7045 R_TimeReport("decals");
7049 if (r_timereport_active)
7050 R_TimeReport("particles");
7053 if (r_timereport_active)
7054 R_TimeReport("explosions");
7056 R_DrawLightningBeams();
7057 if (r_timereport_active)
7058 R_TimeReport("lightning");
7061 VM_CL_AddPolygonsToMeshQueue();
7063 if (r_refdef.view.showdebug)
7065 if (cl_locs_show.integer)
7068 if (r_timereport_active)
7069 R_TimeReport("showlocs");
7072 if (r_drawportals.integer)
7075 if (r_timereport_active)
7076 R_TimeReport("portals");
7079 if (r_showbboxes.value > 0)
7081 R_DrawEntityBBoxes();
7082 if (r_timereport_active)
7083 R_TimeReport("bboxes");
7087 if (r_transparent.integer)
7089 R_MeshQueue_RenderTransparent();
7090 if (r_timereport_active)
7091 R_TimeReport("drawtrans");
7094 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))
7096 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7097 if (r_timereport_active)
7098 R_TimeReport("worlddebug");
7099 R_DrawModelsDebug();
7100 if (r_timereport_active)
7101 R_TimeReport("modeldebug");
7104 if (cl.csqc_vidvars.drawworld)
7106 R_Shadow_DrawCoronas();
7107 if (r_timereport_active)
7108 R_TimeReport("coronas");
7113 GL_DepthTest(false);
7114 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7115 GL_Color(1, 1, 1, 1);
7116 qglBegin(GL_POLYGON);
7117 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7118 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7119 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7120 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7122 qglBegin(GL_POLYGON);
7123 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]);
7124 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]);
7125 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]);
7126 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]);
7128 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7132 // don't let sound skip if going slow
7133 if (r_refdef.scene.extraupdate)
7136 R_ResetViewRendering2D();
7139 static const unsigned short bboxelements[36] =
7149 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7152 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7154 RSurf_ActiveWorldEntity();
7156 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7157 GL_DepthMask(false);
7158 GL_DepthRange(0, 1);
7159 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7160 // R_Mesh_ResetTextureState();
7162 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7163 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7164 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7165 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7166 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7167 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7168 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7169 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7170 R_FillColors(color4f, 8, cr, cg, cb, ca);
7171 if (r_refdef.fogenabled)
7173 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7175 f1 = RSurf_FogVertex(v);
7177 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7178 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7179 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7182 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7183 R_Mesh_ResetTextureState();
7184 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7185 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7188 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7192 prvm_edict_t *edict;
7193 prvm_prog_t *prog_save = prog;
7195 // this function draws bounding boxes of server entities
7199 GL_CullFace(GL_NONE);
7200 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7204 for (i = 0;i < numsurfaces;i++)
7206 edict = PRVM_EDICT_NUM(surfacelist[i]);
7207 switch ((int)PRVM_serveredictfloat(edict, solid))
7209 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7210 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7211 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7212 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7213 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7214 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7216 color[3] *= r_showbboxes.value;
7217 color[3] = bound(0, color[3], 1);
7218 GL_DepthTest(!r_showdisabledepthtest.integer);
7219 GL_CullFace(r_refdef.view.cullface_front);
7220 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7226 static void R_DrawEntityBBoxes(void)
7229 prvm_edict_t *edict;
7231 prvm_prog_t *prog_save = prog;
7233 // this function draws bounding boxes of server entities
7239 for (i = 0;i < prog->num_edicts;i++)
7241 edict = PRVM_EDICT_NUM(i);
7242 if (edict->priv.server->free)
7244 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7245 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7247 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7249 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7250 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7256 static const int nomodelelement3i[24] =
7268 static const unsigned short nomodelelement3s[24] =
7280 static const float nomodelvertex3f[6*3] =
7290 static const float nomodelcolor4f[6*4] =
7292 0.0f, 0.0f, 0.5f, 1.0f,
7293 0.0f, 0.0f, 0.5f, 1.0f,
7294 0.0f, 0.5f, 0.0f, 1.0f,
7295 0.0f, 0.5f, 0.0f, 1.0f,
7296 0.5f, 0.0f, 0.0f, 1.0f,
7297 0.5f, 0.0f, 0.0f, 1.0f
7300 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7306 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);
7308 // this is only called once per entity so numsurfaces is always 1, and
7309 // surfacelist is always {0}, so this code does not handle batches
7311 if (rsurface.ent_flags & RENDER_ADDITIVE)
7313 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7314 GL_DepthMask(false);
7316 else if (rsurface.colormod[3] < 1)
7318 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7319 GL_DepthMask(false);
7323 GL_BlendFunc(GL_ONE, GL_ZERO);
7326 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7327 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7328 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7329 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7330 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7331 for (i = 0, c = color4f;i < 6;i++, c += 4)
7333 c[0] *= rsurface.colormod[0];
7334 c[1] *= rsurface.colormod[1];
7335 c[2] *= rsurface.colormod[2];
7336 c[3] *= rsurface.colormod[3];
7338 if (r_refdef.fogenabled)
7340 for (i = 0, c = color4f;i < 6;i++, c += 4)
7342 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7344 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7345 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7346 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7349 // R_Mesh_ResetTextureState();
7350 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7351 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7352 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7355 void R_DrawNoModel(entity_render_t *ent)
7358 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7359 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7360 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7362 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7365 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7367 vec3_t right1, right2, diff, normal;
7369 VectorSubtract (org2, org1, normal);
7371 // calculate 'right' vector for start
7372 VectorSubtract (r_refdef.view.origin, org1, diff);
7373 CrossProduct (normal, diff, right1);
7374 VectorNormalize (right1);
7376 // calculate 'right' vector for end
7377 VectorSubtract (r_refdef.view.origin, org2, diff);
7378 CrossProduct (normal, diff, right2);
7379 VectorNormalize (right2);
7381 vert[ 0] = org1[0] + width * right1[0];
7382 vert[ 1] = org1[1] + width * right1[1];
7383 vert[ 2] = org1[2] + width * right1[2];
7384 vert[ 3] = org1[0] - width * right1[0];
7385 vert[ 4] = org1[1] - width * right1[1];
7386 vert[ 5] = org1[2] - width * right1[2];
7387 vert[ 6] = org2[0] - width * right2[0];
7388 vert[ 7] = org2[1] - width * right2[1];
7389 vert[ 8] = org2[2] - width * right2[2];
7390 vert[ 9] = org2[0] + width * right2[0];
7391 vert[10] = org2[1] + width * right2[1];
7392 vert[11] = org2[2] + width * right2[2];
7395 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)
7397 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7398 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7399 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7400 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7401 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7402 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7403 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7404 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7405 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7406 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7407 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7408 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7411 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7416 VectorSet(v, x, y, z);
7417 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7418 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7420 if (i == mesh->numvertices)
7422 if (mesh->numvertices < mesh->maxvertices)
7424 VectorCopy(v, vertex3f);
7425 mesh->numvertices++;
7427 return mesh->numvertices;
7433 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7437 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7438 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7439 e = mesh->element3i + mesh->numtriangles * 3;
7440 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7442 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7443 if (mesh->numtriangles < mesh->maxtriangles)
7448 mesh->numtriangles++;
7450 element[1] = element[2];
7454 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7458 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7459 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7460 e = mesh->element3i + mesh->numtriangles * 3;
7461 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7463 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7464 if (mesh->numtriangles < mesh->maxtriangles)
7469 mesh->numtriangles++;
7471 element[1] = element[2];
7475 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7476 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7478 int planenum, planenum2;
7481 mplane_t *plane, *plane2;
7483 double temppoints[2][256*3];
7484 // figure out how large a bounding box we need to properly compute this brush
7486 for (w = 0;w < numplanes;w++)
7487 maxdist = max(maxdist, fabs(planes[w].dist));
7488 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7489 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7490 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7494 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7495 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7497 if (planenum2 == planenum)
7499 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);
7502 if (tempnumpoints < 3)
7504 // generate elements forming a triangle fan for this polygon
7505 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7509 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)
7511 texturelayer_t *layer;
7512 layer = t->currentlayers + t->currentnumlayers++;
7514 layer->depthmask = depthmask;
7515 layer->blendfunc1 = blendfunc1;
7516 layer->blendfunc2 = blendfunc2;
7517 layer->texture = texture;
7518 layer->texmatrix = *matrix;
7519 layer->color[0] = r;
7520 layer->color[1] = g;
7521 layer->color[2] = b;
7522 layer->color[3] = a;
7525 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7527 if(parms[0] == 0 && parms[1] == 0)
7529 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7530 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7535 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7538 index = parms[2] + rsurface.shadertime * parms[3];
7539 index -= floor(index);
7540 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7543 case Q3WAVEFUNC_NONE:
7544 case Q3WAVEFUNC_NOISE:
7545 case Q3WAVEFUNC_COUNT:
7548 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7549 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7550 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7551 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7552 case Q3WAVEFUNC_TRIANGLE:
7554 f = index - floor(index);
7567 f = parms[0] + parms[1] * f;
7568 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7569 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7573 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7579 matrix4x4_t matrix, temp;
7580 switch(tcmod->tcmod)
7584 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7585 matrix = r_waterscrollmatrix;
7587 matrix = identitymatrix;
7589 case Q3TCMOD_ENTITYTRANSLATE:
7590 // this is used in Q3 to allow the gamecode to control texcoord
7591 // scrolling on the entity, which is not supported in darkplaces yet.
7592 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7594 case Q3TCMOD_ROTATE:
7595 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7596 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7597 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7600 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7602 case Q3TCMOD_SCROLL:
7603 // extra care is needed because of precision breakdown with large values of time
7604 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7605 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7606 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7608 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7609 w = (int) tcmod->parms[0];
7610 h = (int) tcmod->parms[1];
7611 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7613 idx = (int) floor(f * w * h);
7614 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7616 case Q3TCMOD_STRETCH:
7617 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7618 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7620 case Q3TCMOD_TRANSFORM:
7621 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7622 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7623 VectorSet(tcmat + 6, 0 , 0 , 1);
7624 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7625 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7627 case Q3TCMOD_TURBULENT:
7628 // this is handled in the RSurf_PrepareVertices function
7629 matrix = identitymatrix;
7633 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7636 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7638 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7639 char name[MAX_QPATH];
7640 skinframe_t *skinframe;
7641 unsigned char pixels[296*194];
7642 strlcpy(cache->name, skinname, sizeof(cache->name));
7643 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7644 if (developer_loading.integer)
7645 Con_Printf("loading %s\n", name);
7646 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7647 if (!skinframe || !skinframe->base)
7650 fs_offset_t filesize;
7652 f = FS_LoadFile(name, tempmempool, true, &filesize);
7655 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7656 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7660 cache->skinframe = skinframe;
7663 texture_t *R_GetCurrentTexture(texture_t *t)
7666 const entity_render_t *ent = rsurface.entity;
7667 dp_model_t *model = ent->model;
7668 q3shaderinfo_layer_tcmod_t *tcmod;
7670 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7671 return t->currentframe;
7672 t->update_lastrenderframe = r_textureframe;
7673 t->update_lastrenderentity = (void *)ent;
7675 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7676 t->camera_entity = ent->entitynumber;
7678 t->camera_entity = 0;
7680 // switch to an alternate material if this is a q1bsp animated material
7682 texture_t *texture = t;
7683 int s = rsurface.ent_skinnum;
7684 if ((unsigned int)s >= (unsigned int)model->numskins)
7686 if (model->skinscenes)
7688 if (model->skinscenes[s].framecount > 1)
7689 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7691 s = model->skinscenes[s].firstframe;
7694 t = t + s * model->num_surfaces;
7697 // use an alternate animation if the entity's frame is not 0,
7698 // and only if the texture has an alternate animation
7699 if (rsurface.ent_alttextures && t->anim_total[1])
7700 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7702 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7704 texture->currentframe = t;
7707 // update currentskinframe to be a qw skin or animation frame
7708 if (rsurface.ent_qwskin >= 0)
7710 i = rsurface.ent_qwskin;
7711 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7713 r_qwskincache_size = cl.maxclients;
7715 Mem_Free(r_qwskincache);
7716 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7718 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7719 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7720 t->currentskinframe = r_qwskincache[i].skinframe;
7721 if (t->currentskinframe == NULL)
7722 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7724 else if (t->numskinframes >= 2)
7725 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7726 if (t->backgroundnumskinframes >= 2)
7727 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7729 t->currentmaterialflags = t->basematerialflags;
7730 t->currentalpha = rsurface.colormod[3];
7731 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7732 t->currentalpha *= r_wateralpha.value;
7733 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7734 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7735 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7736 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7737 if (!(rsurface.ent_flags & RENDER_LIGHT))
7738 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7739 else if (FAKELIGHT_ENABLED)
7741 // no modellight if using fakelight for the map
7743 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7745 // pick a model lighting mode
7746 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7747 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7749 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7751 if (rsurface.ent_flags & RENDER_ADDITIVE)
7752 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7753 else if (t->currentalpha < 1)
7754 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7755 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7756 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7757 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7758 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7759 if (t->backgroundnumskinframes)
7760 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7761 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7763 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7764 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7767 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7768 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7770 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7771 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7773 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7774 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7776 // there is no tcmod
7777 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7779 t->currenttexmatrix = r_waterscrollmatrix;
7780 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7782 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7784 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7785 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7788 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7789 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7790 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7791 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7793 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7794 if (t->currentskinframe->qpixels)
7795 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7796 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7797 if (!t->basetexture)
7798 t->basetexture = r_texture_notexture;
7799 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7800 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7801 t->nmaptexture = t->currentskinframe->nmap;
7802 if (!t->nmaptexture)
7803 t->nmaptexture = r_texture_blanknormalmap;
7804 t->glosstexture = r_texture_black;
7805 t->glowtexture = t->currentskinframe->glow;
7806 t->fogtexture = t->currentskinframe->fog;
7807 t->reflectmasktexture = t->currentskinframe->reflect;
7808 if (t->backgroundnumskinframes)
7810 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7811 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7812 t->backgroundglosstexture = r_texture_black;
7813 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7814 if (!t->backgroundnmaptexture)
7815 t->backgroundnmaptexture = r_texture_blanknormalmap;
7819 t->backgroundbasetexture = r_texture_white;
7820 t->backgroundnmaptexture = r_texture_blanknormalmap;
7821 t->backgroundglosstexture = r_texture_black;
7822 t->backgroundglowtexture = NULL;
7824 t->specularpower = r_shadow_glossexponent.value;
7825 // TODO: store reference values for these in the texture?
7826 t->specularscale = 0;
7827 if (r_shadow_gloss.integer > 0)
7829 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7831 if (r_shadow_glossintensity.value > 0)
7833 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7834 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7835 t->specularscale = r_shadow_glossintensity.value;
7838 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7840 t->glosstexture = r_texture_white;
7841 t->backgroundglosstexture = r_texture_white;
7842 t->specularscale = r_shadow_gloss2intensity.value;
7843 t->specularpower = r_shadow_gloss2exponent.value;
7846 t->specularscale *= t->specularscalemod;
7847 t->specularpower *= t->specularpowermod;
7849 // lightmaps mode looks bad with dlights using actual texturing, so turn
7850 // off the colormap and glossmap, but leave the normalmap on as it still
7851 // accurately represents the shading involved
7852 if (gl_lightmaps.integer)
7854 t->basetexture = r_texture_grey128;
7855 t->pantstexture = r_texture_black;
7856 t->shirttexture = r_texture_black;
7857 t->nmaptexture = r_texture_blanknormalmap;
7858 t->glosstexture = r_texture_black;
7859 t->glowtexture = NULL;
7860 t->fogtexture = NULL;
7861 t->reflectmasktexture = NULL;
7862 t->backgroundbasetexture = NULL;
7863 t->backgroundnmaptexture = r_texture_blanknormalmap;
7864 t->backgroundglosstexture = r_texture_black;
7865 t->backgroundglowtexture = NULL;
7866 t->specularscale = 0;
7867 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7870 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7871 VectorClear(t->dlightcolor);
7872 t->currentnumlayers = 0;
7873 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7875 int blendfunc1, blendfunc2;
7877 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7879 blendfunc1 = GL_SRC_ALPHA;
7880 blendfunc2 = GL_ONE;
7882 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7884 blendfunc1 = GL_SRC_ALPHA;
7885 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7887 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7889 blendfunc1 = t->customblendfunc[0];
7890 blendfunc2 = t->customblendfunc[1];
7894 blendfunc1 = GL_ONE;
7895 blendfunc2 = GL_ZERO;
7897 // don't colormod evilblend textures
7898 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7899 VectorSet(t->lightmapcolor, 1, 1, 1);
7900 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7901 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7903 // fullbright is not affected by r_refdef.lightmapintensity
7904 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]);
7905 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7906 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]);
7907 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7908 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]);
7912 vec3_t ambientcolor;
7914 // set the color tint used for lights affecting this surface
7915 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7917 // q3bsp has no lightmap updates, so the lightstylevalue that
7918 // would normally be baked into the lightmap must be
7919 // applied to the color
7920 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7921 if (model->type == mod_brushq3)
7922 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7923 colorscale *= r_refdef.lightmapintensity;
7924 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7925 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7926 // basic lit geometry
7927 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]);
7928 // add pants/shirt if needed
7929 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7930 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]);
7931 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7932 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]);
7933 // now add ambient passes if needed
7934 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7936 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]);
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] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[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] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7943 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7944 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]);
7945 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7947 // if this is opaque use alpha blend which will darken the earlier
7950 // if this is an alpha blended material, all the earlier passes
7951 // were darkened by fog already, so we only need to add the fog
7952 // color ontop through the fog mask texture
7954 // if this is an additive blended material, all the earlier passes
7955 // were darkened by fog already, and we should not add fog color
7956 // (because the background was not darkened, there is no fog color
7957 // that was lost behind it).
7958 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]);
7962 return t->currentframe;
7965 rsurfacestate_t rsurface;
7967 void RSurf_ActiveWorldEntity(void)
7969 dp_model_t *model = r_refdef.scene.worldmodel;
7970 //if (rsurface.entity == r_refdef.scene.worldentity)
7972 rsurface.entity = r_refdef.scene.worldentity;
7973 rsurface.skeleton = NULL;
7974 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7975 rsurface.ent_skinnum = 0;
7976 rsurface.ent_qwskin = -1;
7977 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7978 rsurface.shadertime = r_refdef.scene.time;
7979 rsurface.matrix = identitymatrix;
7980 rsurface.inversematrix = identitymatrix;
7981 rsurface.matrixscale = 1;
7982 rsurface.inversematrixscale = 1;
7983 R_EntityMatrix(&identitymatrix);
7984 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7985 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7986 rsurface.fograngerecip = r_refdef.fograngerecip;
7987 rsurface.fogheightfade = r_refdef.fogheightfade;
7988 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7989 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7990 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7991 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7992 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7993 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7994 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7995 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7996 rsurface.colormod[3] = 1;
7997 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);
7998 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7999 rsurface.frameblend[0].lerp = 1;
8000 rsurface.ent_alttextures = false;
8001 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8002 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8003 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8004 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8005 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8006 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8007 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8008 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8009 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8010 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8011 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8012 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8013 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8014 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8015 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8016 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8017 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8018 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8019 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8020 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8021 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8022 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8023 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8024 rsurface.modelelement3i = model->surfmesh.data_element3i;
8025 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8026 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8027 rsurface.modelelement3s = model->surfmesh.data_element3s;
8028 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8029 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8030 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8031 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8032 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8033 rsurface.modelsurfaces = model->data_surfaces;
8034 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8035 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8036 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8037 rsurface.modelgeneratedvertex = false;
8038 rsurface.batchgeneratedvertex = false;
8039 rsurface.batchfirstvertex = 0;
8040 rsurface.batchnumvertices = 0;
8041 rsurface.batchfirsttriangle = 0;
8042 rsurface.batchnumtriangles = 0;
8043 rsurface.batchvertex3f = NULL;
8044 rsurface.batchvertex3f_vertexbuffer = NULL;
8045 rsurface.batchvertex3f_bufferoffset = 0;
8046 rsurface.batchsvector3f = NULL;
8047 rsurface.batchsvector3f_vertexbuffer = NULL;
8048 rsurface.batchsvector3f_bufferoffset = 0;
8049 rsurface.batchtvector3f = NULL;
8050 rsurface.batchtvector3f_vertexbuffer = NULL;
8051 rsurface.batchtvector3f_bufferoffset = 0;
8052 rsurface.batchnormal3f = NULL;
8053 rsurface.batchnormal3f_vertexbuffer = NULL;
8054 rsurface.batchnormal3f_bufferoffset = 0;
8055 rsurface.batchlightmapcolor4f = NULL;
8056 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8057 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8058 rsurface.batchtexcoordtexture2f = NULL;
8059 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8060 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8061 rsurface.batchtexcoordlightmap2f = NULL;
8062 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8063 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8064 rsurface.batchvertexmesh = NULL;
8065 rsurface.batchvertexmeshbuffer = NULL;
8066 rsurface.batchvertex3fbuffer = NULL;
8067 rsurface.batchelement3i = NULL;
8068 rsurface.batchelement3i_indexbuffer = NULL;
8069 rsurface.batchelement3i_bufferoffset = 0;
8070 rsurface.batchelement3s = NULL;
8071 rsurface.batchelement3s_indexbuffer = NULL;
8072 rsurface.batchelement3s_bufferoffset = 0;
8073 rsurface.passcolor4f = NULL;
8074 rsurface.passcolor4f_vertexbuffer = NULL;
8075 rsurface.passcolor4f_bufferoffset = 0;
8078 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8080 dp_model_t *model = ent->model;
8081 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8083 rsurface.entity = (entity_render_t *)ent;
8084 rsurface.skeleton = ent->skeleton;
8085 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8086 rsurface.ent_skinnum = ent->skinnum;
8087 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;
8088 rsurface.ent_flags = ent->flags;
8089 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8090 rsurface.matrix = ent->matrix;
8091 rsurface.inversematrix = ent->inversematrix;
8092 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8093 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8094 R_EntityMatrix(&rsurface.matrix);
8095 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8096 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8097 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8098 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8099 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8100 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8101 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8102 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8103 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8104 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8105 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8106 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8107 rsurface.colormod[3] = ent->alpha;
8108 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8109 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8110 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8111 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8112 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8113 if (ent->model->brush.submodel && !prepass)
8115 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8116 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8118 if (model->surfmesh.isanimated && model->AnimateVertices)
8120 if (ent->animcache_vertex3f)
8122 rsurface.modelvertex3f = ent->animcache_vertex3f;
8123 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8124 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8125 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8126 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8127 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8128 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8130 else if (wanttangents)
8132 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8133 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8134 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8135 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8136 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8137 rsurface.modelvertexmesh = NULL;
8138 rsurface.modelvertexmeshbuffer = NULL;
8139 rsurface.modelvertex3fbuffer = NULL;
8141 else if (wantnormals)
8143 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8144 rsurface.modelsvector3f = NULL;
8145 rsurface.modeltvector3f = NULL;
8146 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8147 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8148 rsurface.modelvertexmesh = NULL;
8149 rsurface.modelvertexmeshbuffer = NULL;
8150 rsurface.modelvertex3fbuffer = NULL;
8154 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8155 rsurface.modelsvector3f = NULL;
8156 rsurface.modeltvector3f = NULL;
8157 rsurface.modelnormal3f = NULL;
8158 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8159 rsurface.modelvertexmesh = NULL;
8160 rsurface.modelvertexmeshbuffer = NULL;
8161 rsurface.modelvertex3fbuffer = NULL;
8163 rsurface.modelvertex3f_vertexbuffer = 0;
8164 rsurface.modelvertex3f_bufferoffset = 0;
8165 rsurface.modelsvector3f_vertexbuffer = 0;
8166 rsurface.modelsvector3f_bufferoffset = 0;
8167 rsurface.modeltvector3f_vertexbuffer = 0;
8168 rsurface.modeltvector3f_bufferoffset = 0;
8169 rsurface.modelnormal3f_vertexbuffer = 0;
8170 rsurface.modelnormal3f_bufferoffset = 0;
8171 rsurface.modelgeneratedvertex = true;
8175 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8176 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8177 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8178 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8179 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8180 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8181 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8182 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8183 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8184 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8185 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8186 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8187 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8188 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8189 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8190 rsurface.modelgeneratedvertex = false;
8192 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8193 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8194 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8195 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8196 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8197 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8198 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8199 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8200 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8201 rsurface.modelelement3i = model->surfmesh.data_element3i;
8202 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8203 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8204 rsurface.modelelement3s = model->surfmesh.data_element3s;
8205 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8206 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8207 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8208 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8209 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8210 rsurface.modelsurfaces = model->data_surfaces;
8211 rsurface.batchgeneratedvertex = false;
8212 rsurface.batchfirstvertex = 0;
8213 rsurface.batchnumvertices = 0;
8214 rsurface.batchfirsttriangle = 0;
8215 rsurface.batchnumtriangles = 0;
8216 rsurface.batchvertex3f = NULL;
8217 rsurface.batchvertex3f_vertexbuffer = NULL;
8218 rsurface.batchvertex3f_bufferoffset = 0;
8219 rsurface.batchsvector3f = NULL;
8220 rsurface.batchsvector3f_vertexbuffer = NULL;
8221 rsurface.batchsvector3f_bufferoffset = 0;
8222 rsurface.batchtvector3f = NULL;
8223 rsurface.batchtvector3f_vertexbuffer = NULL;
8224 rsurface.batchtvector3f_bufferoffset = 0;
8225 rsurface.batchnormal3f = NULL;
8226 rsurface.batchnormal3f_vertexbuffer = NULL;
8227 rsurface.batchnormal3f_bufferoffset = 0;
8228 rsurface.batchlightmapcolor4f = NULL;
8229 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8230 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8231 rsurface.batchtexcoordtexture2f = NULL;
8232 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8233 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8234 rsurface.batchtexcoordlightmap2f = NULL;
8235 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8236 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8237 rsurface.batchvertexmesh = NULL;
8238 rsurface.batchvertexmeshbuffer = NULL;
8239 rsurface.batchvertex3fbuffer = NULL;
8240 rsurface.batchelement3i = NULL;
8241 rsurface.batchelement3i_indexbuffer = NULL;
8242 rsurface.batchelement3i_bufferoffset = 0;
8243 rsurface.batchelement3s = NULL;
8244 rsurface.batchelement3s_indexbuffer = NULL;
8245 rsurface.batchelement3s_bufferoffset = 0;
8246 rsurface.passcolor4f = NULL;
8247 rsurface.passcolor4f_vertexbuffer = NULL;
8248 rsurface.passcolor4f_bufferoffset = 0;
8251 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)
8253 rsurface.entity = r_refdef.scene.worldentity;
8254 rsurface.skeleton = NULL;
8255 rsurface.ent_skinnum = 0;
8256 rsurface.ent_qwskin = -1;
8257 rsurface.ent_flags = entflags;
8258 rsurface.shadertime = r_refdef.scene.time - shadertime;
8259 rsurface.modelnumvertices = numvertices;
8260 rsurface.modelnumtriangles = numtriangles;
8261 rsurface.matrix = *matrix;
8262 rsurface.inversematrix = *inversematrix;
8263 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8264 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8265 R_EntityMatrix(&rsurface.matrix);
8266 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8267 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8268 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8269 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8270 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8271 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8272 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8273 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8274 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8275 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8276 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8277 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8278 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);
8279 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8280 rsurface.frameblend[0].lerp = 1;
8281 rsurface.ent_alttextures = false;
8282 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8283 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8286 rsurface.modelvertex3f = (float *)vertex3f;
8287 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8288 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8289 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8291 else if (wantnormals)
8293 rsurface.modelvertex3f = (float *)vertex3f;
8294 rsurface.modelsvector3f = NULL;
8295 rsurface.modeltvector3f = NULL;
8296 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8300 rsurface.modelvertex3f = (float *)vertex3f;
8301 rsurface.modelsvector3f = NULL;
8302 rsurface.modeltvector3f = NULL;
8303 rsurface.modelnormal3f = NULL;
8305 rsurface.modelvertexmesh = NULL;
8306 rsurface.modelvertexmeshbuffer = NULL;
8307 rsurface.modelvertex3fbuffer = NULL;
8308 rsurface.modelvertex3f_vertexbuffer = 0;
8309 rsurface.modelvertex3f_bufferoffset = 0;
8310 rsurface.modelsvector3f_vertexbuffer = 0;
8311 rsurface.modelsvector3f_bufferoffset = 0;
8312 rsurface.modeltvector3f_vertexbuffer = 0;
8313 rsurface.modeltvector3f_bufferoffset = 0;
8314 rsurface.modelnormal3f_vertexbuffer = 0;
8315 rsurface.modelnormal3f_bufferoffset = 0;
8316 rsurface.modelgeneratedvertex = true;
8317 rsurface.modellightmapcolor4f = (float *)color4f;
8318 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8319 rsurface.modellightmapcolor4f_bufferoffset = 0;
8320 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8321 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8322 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8323 rsurface.modeltexcoordlightmap2f = NULL;
8324 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8325 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8326 rsurface.modelelement3i = (int *)element3i;
8327 rsurface.modelelement3i_indexbuffer = NULL;
8328 rsurface.modelelement3i_bufferoffset = 0;
8329 rsurface.modelelement3s = (unsigned short *)element3s;
8330 rsurface.modelelement3s_indexbuffer = NULL;
8331 rsurface.modelelement3s_bufferoffset = 0;
8332 rsurface.modellightmapoffsets = NULL;
8333 rsurface.modelsurfaces = NULL;
8334 rsurface.batchgeneratedvertex = false;
8335 rsurface.batchfirstvertex = 0;
8336 rsurface.batchnumvertices = 0;
8337 rsurface.batchfirsttriangle = 0;
8338 rsurface.batchnumtriangles = 0;
8339 rsurface.batchvertex3f = NULL;
8340 rsurface.batchvertex3f_vertexbuffer = NULL;
8341 rsurface.batchvertex3f_bufferoffset = 0;
8342 rsurface.batchsvector3f = NULL;
8343 rsurface.batchsvector3f_vertexbuffer = NULL;
8344 rsurface.batchsvector3f_bufferoffset = 0;
8345 rsurface.batchtvector3f = NULL;
8346 rsurface.batchtvector3f_vertexbuffer = NULL;
8347 rsurface.batchtvector3f_bufferoffset = 0;
8348 rsurface.batchnormal3f = NULL;
8349 rsurface.batchnormal3f_vertexbuffer = NULL;
8350 rsurface.batchnormal3f_bufferoffset = 0;
8351 rsurface.batchlightmapcolor4f = NULL;
8352 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8353 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8354 rsurface.batchtexcoordtexture2f = NULL;
8355 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8356 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8357 rsurface.batchtexcoordlightmap2f = NULL;
8358 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8359 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8360 rsurface.batchvertexmesh = NULL;
8361 rsurface.batchvertexmeshbuffer = NULL;
8362 rsurface.batchvertex3fbuffer = NULL;
8363 rsurface.batchelement3i = NULL;
8364 rsurface.batchelement3i_indexbuffer = NULL;
8365 rsurface.batchelement3i_bufferoffset = 0;
8366 rsurface.batchelement3s = NULL;
8367 rsurface.batchelement3s_indexbuffer = NULL;
8368 rsurface.batchelement3s_bufferoffset = 0;
8369 rsurface.passcolor4f = NULL;
8370 rsurface.passcolor4f_vertexbuffer = NULL;
8371 rsurface.passcolor4f_bufferoffset = 0;
8373 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8375 if ((wantnormals || wanttangents) && !normal3f)
8377 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8378 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8380 if (wanttangents && !svector3f)
8382 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8383 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8384 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8389 float RSurf_FogPoint(const float *v)
8391 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8392 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8393 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8394 float FogHeightFade = r_refdef.fogheightfade;
8396 unsigned int fogmasktableindex;
8397 if (r_refdef.fogplaneviewabove)
8398 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8400 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8401 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8402 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8405 float RSurf_FogVertex(const float *v)
8407 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8408 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8409 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8410 float FogHeightFade = rsurface.fogheightfade;
8412 unsigned int fogmasktableindex;
8413 if (r_refdef.fogplaneviewabove)
8414 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8416 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8417 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8418 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8421 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8424 for (i = 0;i < numelements;i++)
8425 outelement3i[i] = inelement3i[i] + adjust;
8428 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8429 extern cvar_t gl_vbo;
8430 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8438 int surfacefirsttriangle;
8439 int surfacenumtriangles;
8440 int surfacefirstvertex;
8441 int surfaceendvertex;
8442 int surfacenumvertices;
8443 int batchnumvertices;
8444 int batchnumtriangles;
8448 qboolean dynamicvertex;
8452 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8454 q3shaderinfo_deform_t *deform;
8455 const msurface_t *surface, *firstsurface;
8456 r_vertexmesh_t *vertexmesh;
8457 if (!texturenumsurfaces)
8459 // find vertex range of this surface batch
8461 firstsurface = texturesurfacelist[0];
8462 firsttriangle = firstsurface->num_firsttriangle;
8463 batchnumvertices = 0;
8464 batchnumtriangles = 0;
8465 firstvertex = endvertex = firstsurface->num_firstvertex;
8466 for (i = 0;i < texturenumsurfaces;i++)
8468 surface = texturesurfacelist[i];
8469 if (surface != firstsurface + i)
8471 surfacefirstvertex = surface->num_firstvertex;
8472 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8473 surfacenumvertices = surface->num_vertices;
8474 surfacenumtriangles = surface->num_triangles;
8475 if (firstvertex > surfacefirstvertex)
8476 firstvertex = surfacefirstvertex;
8477 if (endvertex < surfaceendvertex)
8478 endvertex = surfaceendvertex;
8479 batchnumvertices += surfacenumvertices;
8480 batchnumtriangles += surfacenumtriangles;
8483 // we now know the vertex range used, and if there are any gaps in it
8484 rsurface.batchfirstvertex = firstvertex;
8485 rsurface.batchnumvertices = endvertex - firstvertex;
8486 rsurface.batchfirsttriangle = firsttriangle;
8487 rsurface.batchnumtriangles = batchnumtriangles;
8489 // this variable holds flags for which properties have been updated that
8490 // may require regenerating vertexmesh array...
8493 // check if any dynamic vertex processing must occur
8494 dynamicvertex = false;
8496 // if there is a chance of animated vertex colors, it's a dynamic batch
8497 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8499 dynamicvertex = true;
8500 batchneed |= BATCHNEED_NOGAPS;
8501 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8504 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8506 switch (deform->deform)
8509 case Q3DEFORM_PROJECTIONSHADOW:
8510 case Q3DEFORM_TEXT0:
8511 case Q3DEFORM_TEXT1:
8512 case Q3DEFORM_TEXT2:
8513 case Q3DEFORM_TEXT3:
8514 case Q3DEFORM_TEXT4:
8515 case Q3DEFORM_TEXT5:
8516 case Q3DEFORM_TEXT6:
8517 case Q3DEFORM_TEXT7:
8520 case Q3DEFORM_AUTOSPRITE:
8521 dynamicvertex = true;
8522 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8523 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8525 case Q3DEFORM_AUTOSPRITE2:
8526 dynamicvertex = true;
8527 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8528 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8530 case Q3DEFORM_NORMAL:
8531 dynamicvertex = true;
8532 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8533 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8536 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8537 break; // if wavefunc is a nop, ignore this transform
8538 dynamicvertex = true;
8539 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8540 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8542 case Q3DEFORM_BULGE:
8543 dynamicvertex = true;
8544 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8545 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8548 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8549 break; // if wavefunc is a nop, ignore this transform
8550 dynamicvertex = true;
8551 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8552 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8556 switch(rsurface.texture->tcgen.tcgen)
8559 case Q3TCGEN_TEXTURE:
8561 case Q3TCGEN_LIGHTMAP:
8562 dynamicvertex = true;
8563 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8564 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8566 case Q3TCGEN_VECTOR:
8567 dynamicvertex = true;
8568 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8569 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8571 case Q3TCGEN_ENVIRONMENT:
8572 dynamicvertex = true;
8573 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8574 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8577 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8579 dynamicvertex = true;
8580 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8581 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8584 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8586 dynamicvertex = true;
8587 batchneed |= BATCHNEED_NOGAPS;
8588 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8591 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8593 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8594 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8595 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8596 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8597 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8598 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8599 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8602 // when the model data has no vertex buffer (dynamic mesh), we need to
8604 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8605 batchneed |= BATCHNEED_NOGAPS;
8607 // if needsupdate, we have to do a dynamic vertex batch for sure
8608 if (needsupdate & batchneed)
8609 dynamicvertex = true;
8611 // see if we need to build vertexmesh from arrays
8612 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8613 dynamicvertex = true;
8615 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8616 // also some drivers strongly dislike firstvertex
8617 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8618 dynamicvertex = true;
8620 rsurface.batchvertex3f = rsurface.modelvertex3f;
8621 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8622 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8623 rsurface.batchsvector3f = rsurface.modelsvector3f;
8624 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8625 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8626 rsurface.batchtvector3f = rsurface.modeltvector3f;
8627 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8628 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8629 rsurface.batchnormal3f = rsurface.modelnormal3f;
8630 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8631 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8632 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8633 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8634 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8635 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8636 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8637 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8638 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8639 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8640 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8641 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8642 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8643 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8644 rsurface.batchelement3i = rsurface.modelelement3i;
8645 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8646 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8647 rsurface.batchelement3s = rsurface.modelelement3s;
8648 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8649 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8651 // if any dynamic vertex processing has to occur in software, we copy the
8652 // entire surface list together before processing to rebase the vertices
8653 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8655 // if any gaps exist and we do not have a static vertex buffer, we have to
8656 // copy the surface list together to avoid wasting upload bandwidth on the
8657 // vertices in the gaps.
8659 // if gaps exist and we have a static vertex buffer, we still have to
8660 // combine the index buffer ranges into one dynamic index buffer.
8662 // in all cases we end up with data that can be drawn in one call.
8666 // static vertex data, just set pointers...
8667 rsurface.batchgeneratedvertex = false;
8668 // if there are gaps, we want to build a combined index buffer,
8669 // otherwise use the original static buffer with an appropriate offset
8672 // build a new triangle elements array for this batch
8673 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8674 rsurface.batchfirsttriangle = 0;
8676 for (i = 0;i < texturenumsurfaces;i++)
8678 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8679 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8680 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8681 numtriangles += surfacenumtriangles;
8683 rsurface.batchelement3i_indexbuffer = NULL;
8684 rsurface.batchelement3i_bufferoffset = 0;
8685 rsurface.batchelement3s = NULL;
8686 rsurface.batchelement3s_indexbuffer = NULL;
8687 rsurface.batchelement3s_bufferoffset = 0;
8688 if (endvertex <= 65536)
8690 // make a 16bit (unsigned short) index array if possible
8691 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8692 for (i = 0;i < numtriangles*3;i++)
8693 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8699 // something needs software processing, do it for real...
8700 // we only directly handle separate array data in this case and then
8701 // generate interleaved data if needed...
8702 rsurface.batchgeneratedvertex = true;
8704 // now copy the vertex data into a combined array and make an index array
8705 // (this is what Quake3 does all the time)
8706 //if (gaps || rsurface.batchfirstvertex)
8708 rsurface.batchvertex3fbuffer = NULL;
8709 rsurface.batchvertexmesh = NULL;
8710 rsurface.batchvertexmeshbuffer = NULL;
8711 rsurface.batchvertex3f = NULL;
8712 rsurface.batchvertex3f_vertexbuffer = NULL;
8713 rsurface.batchvertex3f_bufferoffset = 0;
8714 rsurface.batchsvector3f = NULL;
8715 rsurface.batchsvector3f_vertexbuffer = NULL;
8716 rsurface.batchsvector3f_bufferoffset = 0;
8717 rsurface.batchtvector3f = NULL;
8718 rsurface.batchtvector3f_vertexbuffer = NULL;
8719 rsurface.batchtvector3f_bufferoffset = 0;
8720 rsurface.batchnormal3f = NULL;
8721 rsurface.batchnormal3f_vertexbuffer = NULL;
8722 rsurface.batchnormal3f_bufferoffset = 0;
8723 rsurface.batchlightmapcolor4f = NULL;
8724 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8725 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8726 rsurface.batchtexcoordtexture2f = NULL;
8727 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8728 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8729 rsurface.batchtexcoordlightmap2f = NULL;
8730 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8731 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8732 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8733 rsurface.batchelement3i_indexbuffer = NULL;
8734 rsurface.batchelement3i_bufferoffset = 0;
8735 rsurface.batchelement3s = NULL;
8736 rsurface.batchelement3s_indexbuffer = NULL;
8737 rsurface.batchelement3s_bufferoffset = 0;
8738 // we'll only be setting up certain arrays as needed
8739 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8740 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8741 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8742 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8743 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8744 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8745 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8747 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8748 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8750 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8751 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8752 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8753 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8754 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8755 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8758 for (i = 0;i < texturenumsurfaces;i++)
8760 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8761 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8762 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8763 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8764 // copy only the data requested
8765 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8766 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8767 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8769 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8771 if (rsurface.batchvertex3f)
8772 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8774 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8776 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8778 if (rsurface.modelnormal3f)
8779 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8781 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8783 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8785 if (rsurface.modelsvector3f)
8787 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8788 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8792 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8793 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8796 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8798 if (rsurface.modellightmapcolor4f)
8799 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8801 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8803 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8805 if (rsurface.modeltexcoordtexture2f)
8806 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8808 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8810 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8812 if (rsurface.modeltexcoordlightmap2f)
8813 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8815 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8818 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8819 numvertices += surfacenumvertices;
8820 numtriangles += surfacenumtriangles;
8823 // generate a 16bit index array as well if possible
8824 // (in general, dynamic batches fit)
8825 if (numvertices <= 65536)
8827 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8828 for (i = 0;i < numtriangles*3;i++)
8829 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8832 // since we've copied everything, the batch now starts at 0
8833 rsurface.batchfirstvertex = 0;
8834 rsurface.batchnumvertices = batchnumvertices;
8835 rsurface.batchfirsttriangle = 0;
8836 rsurface.batchnumtriangles = batchnumtriangles;
8839 // q1bsp surfaces rendered in vertex color mode have to have colors
8840 // calculated based on lightstyles
8841 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8843 // generate color arrays for the surfaces in this list
8848 const unsigned char *lm;
8849 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8850 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8851 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8853 for (i = 0;i < texturenumsurfaces;i++)
8855 surface = texturesurfacelist[i];
8856 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8857 surfacenumvertices = surface->num_vertices;
8858 if (surface->lightmapinfo->samples)
8860 for (j = 0;j < surfacenumvertices;j++)
8862 lm = surface->lightmapinfo->samples + offsets[j];
8863 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8864 VectorScale(lm, scale, c);
8865 if (surface->lightmapinfo->styles[1] != 255)
8867 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8869 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8870 VectorMA(c, scale, lm, c);
8871 if (surface->lightmapinfo->styles[2] != 255)
8874 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8875 VectorMA(c, scale, lm, c);
8876 if (surface->lightmapinfo->styles[3] != 255)
8879 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8880 VectorMA(c, scale, lm, c);
8887 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);
8893 for (j = 0;j < surfacenumvertices;j++)
8895 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8902 // if vertices are deformed (sprite flares and things in maps, possibly
8903 // water waves, bulges and other deformations), modify the copied vertices
8905 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8907 switch (deform->deform)
8910 case Q3DEFORM_PROJECTIONSHADOW:
8911 case Q3DEFORM_TEXT0:
8912 case Q3DEFORM_TEXT1:
8913 case Q3DEFORM_TEXT2:
8914 case Q3DEFORM_TEXT3:
8915 case Q3DEFORM_TEXT4:
8916 case Q3DEFORM_TEXT5:
8917 case Q3DEFORM_TEXT6:
8918 case Q3DEFORM_TEXT7:
8921 case Q3DEFORM_AUTOSPRITE:
8922 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8923 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8924 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8925 VectorNormalize(newforward);
8926 VectorNormalize(newright);
8927 VectorNormalize(newup);
8928 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8929 // rsurface.batchvertex3f_vertexbuffer = NULL;
8930 // rsurface.batchvertex3f_bufferoffset = 0;
8931 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8932 // rsurface.batchsvector3f_vertexbuffer = NULL;
8933 // rsurface.batchsvector3f_bufferoffset = 0;
8934 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8935 // rsurface.batchtvector3f_vertexbuffer = NULL;
8936 // rsurface.batchtvector3f_bufferoffset = 0;
8937 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8938 // rsurface.batchnormal3f_vertexbuffer = NULL;
8939 // rsurface.batchnormal3f_bufferoffset = 0;
8940 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8941 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8942 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8943 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8944 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);
8945 // a single autosprite surface can contain multiple sprites...
8946 for (j = 0;j < batchnumvertices - 3;j += 4)
8948 VectorClear(center);
8949 for (i = 0;i < 4;i++)
8950 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8951 VectorScale(center, 0.25f, center);
8952 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8953 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8954 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8955 for (i = 0;i < 4;i++)
8957 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8958 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8961 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8962 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8963 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);
8965 case Q3DEFORM_AUTOSPRITE2:
8966 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8967 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8968 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8969 VectorNormalize(newforward);
8970 VectorNormalize(newright);
8971 VectorNormalize(newup);
8972 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8973 // rsurface.batchvertex3f_vertexbuffer = NULL;
8974 // rsurface.batchvertex3f_bufferoffset = 0;
8976 const float *v1, *v2;
8986 memset(shortest, 0, sizeof(shortest));
8987 // a single autosprite surface can contain multiple sprites...
8988 for (j = 0;j < batchnumvertices - 3;j += 4)
8990 VectorClear(center);
8991 for (i = 0;i < 4;i++)
8992 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8993 VectorScale(center, 0.25f, center);
8994 // find the two shortest edges, then use them to define the
8995 // axis vectors for rotating around the central axis
8996 for (i = 0;i < 6;i++)
8998 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8999 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9000 l = VectorDistance2(v1, v2);
9001 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9003 l += (1.0f / 1024.0f);
9004 if (shortest[0].length2 > l || i == 0)
9006 shortest[1] = shortest[0];
9007 shortest[0].length2 = l;
9008 shortest[0].v1 = v1;
9009 shortest[0].v2 = v2;
9011 else if (shortest[1].length2 > l || i == 1)
9013 shortest[1].length2 = l;
9014 shortest[1].v1 = v1;
9015 shortest[1].v2 = v2;
9018 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9019 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9020 // this calculates the right vector from the shortest edge
9021 // and the up vector from the edge midpoints
9022 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9023 VectorNormalize(right);
9024 VectorSubtract(end, start, up);
9025 VectorNormalize(up);
9026 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9027 VectorSubtract(rsurface.localvieworigin, center, forward);
9028 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9029 VectorNegate(forward, forward);
9030 VectorReflect(forward, 0, up, forward);
9031 VectorNormalize(forward);
9032 CrossProduct(up, forward, newright);
9033 VectorNormalize(newright);
9034 // rotate the quad around the up axis vector, this is made
9035 // especially easy by the fact we know the quad is flat,
9036 // so we only have to subtract the center position and
9037 // measure distance along the right vector, and then
9038 // multiply that by the newright vector and add back the
9040 // we also need to subtract the old position to undo the
9041 // displacement from the center, which we do with a
9042 // DotProduct, the subtraction/addition of center is also
9043 // optimized into DotProducts here
9044 l = DotProduct(right, center);
9045 for (i = 0;i < 4;i++)
9047 v1 = rsurface.batchvertex3f + 3*(j+i);
9048 f = DotProduct(right, v1) - l;
9049 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9053 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9055 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9056 // rsurface.batchnormal3f_vertexbuffer = NULL;
9057 // rsurface.batchnormal3f_bufferoffset = 0;
9058 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9060 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9062 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9063 // rsurface.batchsvector3f_vertexbuffer = NULL;
9064 // rsurface.batchsvector3f_bufferoffset = 0;
9065 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9066 // rsurface.batchtvector3f_vertexbuffer = NULL;
9067 // rsurface.batchtvector3f_bufferoffset = 0;
9068 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);
9071 case Q3DEFORM_NORMAL:
9072 // deform the normals to make reflections wavey
9073 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9074 rsurface.batchnormal3f_vertexbuffer = NULL;
9075 rsurface.batchnormal3f_bufferoffset = 0;
9076 for (j = 0;j < batchnumvertices;j++)
9079 float *normal = rsurface.batchnormal3f + 3*j;
9080 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9081 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9082 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9083 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9084 VectorNormalize(normal);
9086 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9088 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9089 // rsurface.batchsvector3f_vertexbuffer = NULL;
9090 // rsurface.batchsvector3f_bufferoffset = 0;
9091 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9092 // rsurface.batchtvector3f_vertexbuffer = NULL;
9093 // rsurface.batchtvector3f_bufferoffset = 0;
9094 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);
9098 // deform vertex array to make wavey water and flags and such
9099 waveparms[0] = deform->waveparms[0];
9100 waveparms[1] = deform->waveparms[1];
9101 waveparms[2] = deform->waveparms[2];
9102 waveparms[3] = deform->waveparms[3];
9103 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9104 break; // if wavefunc is a nop, don't make a dynamic vertex array
9105 // this is how a divisor of vertex influence on deformation
9106 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9107 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9108 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9109 // rsurface.batchvertex3f_vertexbuffer = NULL;
9110 // rsurface.batchvertex3f_bufferoffset = 0;
9111 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9112 // rsurface.batchnormal3f_vertexbuffer = NULL;
9113 // rsurface.batchnormal3f_bufferoffset = 0;
9114 for (j = 0;j < batchnumvertices;j++)
9116 // if the wavefunc depends on time, evaluate it per-vertex
9119 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9120 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9122 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9124 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9125 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9126 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9128 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9129 // rsurface.batchsvector3f_vertexbuffer = NULL;
9130 // rsurface.batchsvector3f_bufferoffset = 0;
9131 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9132 // rsurface.batchtvector3f_vertexbuffer = NULL;
9133 // rsurface.batchtvector3f_bufferoffset = 0;
9134 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);
9137 case Q3DEFORM_BULGE:
9138 // deform vertex array to make the surface have moving bulges
9139 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9140 // rsurface.batchvertex3f_vertexbuffer = NULL;
9141 // rsurface.batchvertex3f_bufferoffset = 0;
9142 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9143 // rsurface.batchnormal3f_vertexbuffer = NULL;
9144 // rsurface.batchnormal3f_bufferoffset = 0;
9145 for (j = 0;j < batchnumvertices;j++)
9147 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9148 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9150 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9151 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9152 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9154 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9155 // rsurface.batchsvector3f_vertexbuffer = NULL;
9156 // rsurface.batchsvector3f_bufferoffset = 0;
9157 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9158 // rsurface.batchtvector3f_vertexbuffer = NULL;
9159 // rsurface.batchtvector3f_bufferoffset = 0;
9160 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);
9164 // deform vertex array
9165 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9166 break; // if wavefunc is a nop, don't make a dynamic vertex array
9167 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9168 VectorScale(deform->parms, scale, waveparms);
9169 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9170 // rsurface.batchvertex3f_vertexbuffer = NULL;
9171 // rsurface.batchvertex3f_bufferoffset = 0;
9172 for (j = 0;j < batchnumvertices;j++)
9173 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9178 // generate texcoords based on the chosen texcoord source
9179 switch(rsurface.texture->tcgen.tcgen)
9182 case Q3TCGEN_TEXTURE:
9184 case Q3TCGEN_LIGHTMAP:
9185 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9186 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9187 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9188 if (rsurface.batchtexcoordlightmap2f)
9189 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9191 case Q3TCGEN_VECTOR:
9192 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9193 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9194 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9195 for (j = 0;j < batchnumvertices;j++)
9197 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9198 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9201 case Q3TCGEN_ENVIRONMENT:
9202 // make environment reflections using a spheremap
9203 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9204 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9205 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9206 for (j = 0;j < batchnumvertices;j++)
9208 // identical to Q3A's method, but executed in worldspace so
9209 // carried models can be shiny too
9211 float viewer[3], d, reflected[3], worldreflected[3];
9213 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9214 // VectorNormalize(viewer);
9216 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9218 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9219 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9220 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9221 // note: this is proportinal to viewer, so we can normalize later
9223 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9224 VectorNormalize(worldreflected);
9226 // note: this sphere map only uses world x and z!
9227 // so positive and negative y will LOOK THE SAME.
9228 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9229 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9233 // the only tcmod that needs software vertex processing is turbulent, so
9234 // check for it here and apply the changes if needed
9235 // and we only support that as the first one
9236 // (handling a mixture of turbulent and other tcmods would be problematic
9237 // without punting it entirely to a software path)
9238 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9240 amplitude = rsurface.texture->tcmods[0].parms[1];
9241 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9242 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9243 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9244 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9245 for (j = 0;j < batchnumvertices;j++)
9247 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);
9248 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9252 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9254 // convert the modified arrays to vertex structs
9255 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9256 // rsurface.batchvertexmeshbuffer = NULL;
9257 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9258 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9259 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9260 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9261 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9262 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9263 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9265 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9267 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9268 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9271 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9272 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9273 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9274 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9275 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9276 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9277 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9278 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9279 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9283 void RSurf_DrawBatch(void)
9285 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9286 // through the pipeline, killing it earlier in the pipeline would have
9287 // per-surface overhead rather than per-batch overhead, so it's best to
9288 // reject it here, before it hits glDraw.
9289 if (rsurface.batchnumtriangles == 0)
9292 // batch debugging code
9293 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9299 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9300 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9303 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9305 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9307 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9308 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);
9315 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);
9318 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9320 // pick the closest matching water plane
9321 int planeindex, vertexindex, bestplaneindex = -1;
9325 r_waterstate_waterplane_t *p;
9326 qboolean prepared = false;
9328 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9330 if(p->camera_entity != rsurface.texture->camera_entity)
9335 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9337 if(rsurface.batchnumvertices == 0)
9340 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9342 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9343 d += fabs(PlaneDiff(vert, &p->plane));
9345 if (bestd > d || bestplaneindex < 0)
9348 bestplaneindex = planeindex;
9351 return bestplaneindex;
9352 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9353 // this situation though, as it might be better to render single larger
9354 // batches with useless stuff (backface culled for example) than to
9355 // render multiple smaller batches
9358 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9361 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9362 rsurface.passcolor4f_vertexbuffer = 0;
9363 rsurface.passcolor4f_bufferoffset = 0;
9364 for (i = 0;i < rsurface.batchnumvertices;i++)
9365 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9368 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9375 if (rsurface.passcolor4f)
9377 // generate color arrays
9378 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9379 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9380 rsurface.passcolor4f_vertexbuffer = 0;
9381 rsurface.passcolor4f_bufferoffset = 0;
9382 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)
9384 f = RSurf_FogVertex(v);
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, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9398 f = RSurf_FogVertex(v);
9407 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9414 if (!rsurface.passcolor4f)
9416 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9417 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9418 rsurface.passcolor4f_vertexbuffer = 0;
9419 rsurface.passcolor4f_bufferoffset = 0;
9420 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)
9422 f = RSurf_FogVertex(v);
9423 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9424 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9425 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9430 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9435 if (!rsurface.passcolor4f)
9437 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9438 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9439 rsurface.passcolor4f_vertexbuffer = 0;
9440 rsurface.passcolor4f_bufferoffset = 0;
9441 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9450 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9455 if (!rsurface.passcolor4f)
9457 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9458 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9459 rsurface.passcolor4f_vertexbuffer = 0;
9460 rsurface.passcolor4f_bufferoffset = 0;
9461 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9463 c2[0] = c[0] + r_refdef.scene.ambient;
9464 c2[1] = c[1] + r_refdef.scene.ambient;
9465 c2[2] = c[2] + r_refdef.scene.ambient;
9470 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9473 rsurface.passcolor4f = NULL;
9474 rsurface.passcolor4f_vertexbuffer = 0;
9475 rsurface.passcolor4f_bufferoffset = 0;
9476 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9477 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9478 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9479 GL_Color(r, g, b, a);
9480 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9484 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9486 // TODO: optimize applyfog && applycolor case
9487 // just apply fog if necessary, and tint the fog color array if necessary
9488 rsurface.passcolor4f = NULL;
9489 rsurface.passcolor4f_vertexbuffer = 0;
9490 rsurface.passcolor4f_bufferoffset = 0;
9491 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9492 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9493 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9494 GL_Color(r, g, b, a);
9498 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9501 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9502 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9503 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9504 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9505 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9506 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9507 GL_Color(r, g, b, a);
9511 static void RSurf_DrawBatch_GL11_ClampColor(void)
9516 if (!rsurface.passcolor4f)
9518 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9520 c2[0] = bound(0.0f, c1[0], 1.0f);
9521 c2[1] = bound(0.0f, c1[1], 1.0f);
9522 c2[2] = bound(0.0f, c1[2], 1.0f);
9523 c2[3] = bound(0.0f, c1[3], 1.0f);
9527 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9537 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9538 rsurface.passcolor4f_vertexbuffer = 0;
9539 rsurface.passcolor4f_bufferoffset = 0;
9540 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)
9542 f = -DotProduct(r_refdef.view.forward, n);
9544 f = f * 0.85 + 0.15; // work around so stuff won't get black
9545 f *= r_refdef.lightmapintensity;
9546 Vector4Set(c, f, f, f, 1);
9550 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9552 RSurf_DrawBatch_GL11_ApplyFakeLight();
9553 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9554 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9555 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9556 GL_Color(r, g, b, a);
9560 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9568 vec3_t ambientcolor;
9569 vec3_t diffusecolor;
9573 VectorCopy(rsurface.modellight_lightdir, lightdir);
9574 f = 0.5f * r_refdef.lightmapintensity;
9575 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9576 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9577 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9578 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9579 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9580 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9582 if (VectorLength2(diffusecolor) > 0)
9584 // q3-style directional shading
9585 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9586 rsurface.passcolor4f_vertexbuffer = 0;
9587 rsurface.passcolor4f_bufferoffset = 0;
9588 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)
9590 if ((f = DotProduct(n, lightdir)) > 0)
9591 VectorMA(ambientcolor, f, diffusecolor, c);
9593 VectorCopy(ambientcolor, c);
9600 *applycolor = false;
9604 *r = ambientcolor[0];
9605 *g = ambientcolor[1];
9606 *b = ambientcolor[2];
9607 rsurface.passcolor4f = NULL;
9608 rsurface.passcolor4f_vertexbuffer = 0;
9609 rsurface.passcolor4f_bufferoffset = 0;
9613 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9615 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9616 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9617 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9618 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9619 GL_Color(r, g, b, a);
9623 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9631 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9632 rsurface.passcolor4f_vertexbuffer = 0;
9633 rsurface.passcolor4f_bufferoffset = 0;
9635 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9637 f = 1 - RSurf_FogVertex(v);
9645 void RSurf_SetupDepthAndCulling(void)
9647 // submodels are biased to avoid z-fighting with world surfaces that they
9648 // may be exactly overlapping (avoids z-fighting artifacts on certain
9649 // doors and things in Quake maps)
9650 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9651 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9652 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9653 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9656 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9658 // transparent sky would be ridiculous
9659 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9661 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9662 skyrenderlater = true;
9663 RSurf_SetupDepthAndCulling();
9665 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9666 // skymasking on them, and Quake3 never did sky masking (unlike
9667 // software Quake and software Quake2), so disable the sky masking
9668 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9669 // and skymasking also looks very bad when noclipping outside the
9670 // level, so don't use it then either.
9671 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9673 R_Mesh_ResetTextureState();
9674 if (skyrendermasked)
9676 R_SetupShader_DepthOrShadow(false);
9677 // depth-only (masking)
9678 GL_ColorMask(0,0,0,0);
9679 // just to make sure that braindead drivers don't draw
9680 // anything despite that colormask...
9681 GL_BlendFunc(GL_ZERO, GL_ONE);
9682 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9683 if (rsurface.batchvertex3fbuffer)
9684 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9686 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9690 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9692 GL_BlendFunc(GL_ONE, GL_ZERO);
9693 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9694 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9695 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9698 if (skyrendermasked)
9699 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9701 R_Mesh_ResetTextureState();
9702 GL_Color(1, 1, 1, 1);
9705 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9706 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9707 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9709 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9713 // render screenspace normalmap to texture
9715 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9719 // bind lightmap texture
9721 // water/refraction/reflection/camera surfaces have to be handled specially
9722 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9724 int start, end, startplaneindex;
9725 for (start = 0;start < texturenumsurfaces;start = end)
9727 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9728 if(startplaneindex < 0)
9730 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9731 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9735 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9737 // now that we have a batch using the same planeindex, render it
9738 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9740 // render water or distortion background
9742 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);
9744 // blend surface on top
9745 GL_DepthMask(false);
9746 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9749 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9751 // render surface with reflection texture as input
9752 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9753 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);
9760 // render surface batch normally
9761 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9762 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);
9766 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9768 // OpenGL 1.3 path - anything not completely ancient
9769 qboolean applycolor;
9772 const texturelayer_t *layer;
9773 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);
9774 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9776 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9779 int layertexrgbscale;
9780 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9782 if (layerindex == 0)
9786 GL_AlphaTest(false);
9787 GL_DepthFunc(GL_EQUAL);
9790 GL_DepthMask(layer->depthmask && writedepth);
9791 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9792 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9794 layertexrgbscale = 4;
9795 VectorScale(layer->color, 0.25f, layercolor);
9797 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9799 layertexrgbscale = 2;
9800 VectorScale(layer->color, 0.5f, layercolor);
9804 layertexrgbscale = 1;
9805 VectorScale(layer->color, 1.0f, layercolor);
9807 layercolor[3] = layer->color[3];
9808 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9809 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9810 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9811 switch (layer->type)
9813 case TEXTURELAYERTYPE_LITTEXTURE:
9814 // single-pass lightmapped texture with 2x rgbscale
9815 R_Mesh_TexBind(0, r_texture_white);
9816 R_Mesh_TexMatrix(0, NULL);
9817 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9818 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9819 R_Mesh_TexBind(1, layer->texture);
9820 R_Mesh_TexMatrix(1, &layer->texmatrix);
9821 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9822 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9823 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9824 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9825 else if (FAKELIGHT_ENABLED)
9826 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9827 else if (rsurface.uselightmaptexture)
9828 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9830 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9832 case TEXTURELAYERTYPE_TEXTURE:
9833 // singletexture unlit texture with transparency support
9834 R_Mesh_TexBind(0, layer->texture);
9835 R_Mesh_TexMatrix(0, &layer->texmatrix);
9836 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9837 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9838 R_Mesh_TexBind(1, 0);
9839 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9840 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9842 case TEXTURELAYERTYPE_FOG:
9843 // singletexture fogging
9846 R_Mesh_TexBind(0, layer->texture);
9847 R_Mesh_TexMatrix(0, &layer->texmatrix);
9848 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9849 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9853 R_Mesh_TexBind(0, 0);
9854 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9856 R_Mesh_TexBind(1, 0);
9857 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9858 // generate a color array for the fog pass
9859 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9860 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9864 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9867 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9869 GL_DepthFunc(GL_LEQUAL);
9870 GL_AlphaTest(false);
9874 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9876 // OpenGL 1.1 - crusty old voodoo path
9879 const texturelayer_t *layer;
9880 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);
9881 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9883 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9885 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9887 if (layerindex == 0)
9891 GL_AlphaTest(false);
9892 GL_DepthFunc(GL_EQUAL);
9895 GL_DepthMask(layer->depthmask && writedepth);
9896 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9897 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9898 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9899 switch (layer->type)
9901 case TEXTURELAYERTYPE_LITTEXTURE:
9902 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9904 // two-pass lit texture with 2x rgbscale
9905 // first the lightmap pass
9906 R_Mesh_TexBind(0, r_texture_white);
9907 R_Mesh_TexMatrix(0, NULL);
9908 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9909 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9910 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9911 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9912 else if (FAKELIGHT_ENABLED)
9913 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9914 else if (rsurface.uselightmaptexture)
9915 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9917 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9918 // then apply the texture to it
9919 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9920 R_Mesh_TexBind(0, layer->texture);
9921 R_Mesh_TexMatrix(0, &layer->texmatrix);
9922 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9923 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9924 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);
9928 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9929 R_Mesh_TexBind(0, layer->texture);
9930 R_Mesh_TexMatrix(0, &layer->texmatrix);
9931 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9932 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9933 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9934 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);
9936 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);
9939 case TEXTURELAYERTYPE_TEXTURE:
9940 // singletexture unlit texture with transparency support
9941 R_Mesh_TexBind(0, layer->texture);
9942 R_Mesh_TexMatrix(0, &layer->texmatrix);
9943 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9944 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9945 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);
9947 case TEXTURELAYERTYPE_FOG:
9948 // singletexture fogging
9951 R_Mesh_TexBind(0, layer->texture);
9952 R_Mesh_TexMatrix(0, &layer->texmatrix);
9953 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9954 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9958 R_Mesh_TexBind(0, 0);
9959 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9961 // generate a color array for the fog pass
9962 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9963 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9967 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9970 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9972 GL_DepthFunc(GL_LEQUAL);
9973 GL_AlphaTest(false);
9977 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9981 r_vertexgeneric_t *batchvertex;
9984 // R_Mesh_ResetTextureState();
9985 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9987 if(rsurface.texture && rsurface.texture->currentskinframe)
9989 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9990 c[3] *= rsurface.texture->currentalpha;
10000 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10002 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10003 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10004 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10007 // brighten it up (as texture value 127 means "unlit")
10008 c[0] *= 2 * r_refdef.view.colorscale;
10009 c[1] *= 2 * r_refdef.view.colorscale;
10010 c[2] *= 2 * r_refdef.view.colorscale;
10012 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10013 c[3] *= r_wateralpha.value;
10015 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10017 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10018 GL_DepthMask(false);
10020 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10022 GL_BlendFunc(GL_ONE, GL_ONE);
10023 GL_DepthMask(false);
10025 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10027 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10028 GL_DepthMask(false);
10030 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10032 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10033 GL_DepthMask(false);
10037 GL_BlendFunc(GL_ONE, GL_ZERO);
10038 GL_DepthMask(writedepth);
10041 if (r_showsurfaces.integer == 3)
10043 rsurface.passcolor4f = NULL;
10045 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10047 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10049 rsurface.passcolor4f = NULL;
10050 rsurface.passcolor4f_vertexbuffer = 0;
10051 rsurface.passcolor4f_bufferoffset = 0;
10053 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10055 qboolean applycolor = true;
10058 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10060 r_refdef.lightmapintensity = 1;
10061 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10062 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10064 else if (FAKELIGHT_ENABLED)
10066 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10068 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10069 RSurf_DrawBatch_GL11_ApplyFakeLight();
10070 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10074 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10076 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10077 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10078 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10081 if(!rsurface.passcolor4f)
10082 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10084 RSurf_DrawBatch_GL11_ApplyAmbient();
10085 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10086 if(r_refdef.fogenabled)
10087 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10088 RSurf_DrawBatch_GL11_ClampColor();
10090 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10091 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10094 else if (!r_refdef.view.showdebug)
10096 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10097 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10098 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10100 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10101 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10103 R_Mesh_PrepareVertices_Generic_Unlock();
10106 else if (r_showsurfaces.integer == 4)
10108 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10109 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10110 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10112 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10113 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10114 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10116 R_Mesh_PrepareVertices_Generic_Unlock();
10119 else if (r_showsurfaces.integer == 2)
10122 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10123 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10124 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10126 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10127 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10128 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10129 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10130 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10131 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10132 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10134 R_Mesh_PrepareVertices_Generic_Unlock();
10135 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10139 int texturesurfaceindex;
10141 const msurface_t *surface;
10142 float surfacecolor4f[4];
10143 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10144 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10146 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10148 surface = texturesurfacelist[texturesurfaceindex];
10149 k = (int)(((size_t)surface) / sizeof(msurface_t));
10150 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10151 for (j = 0;j < surface->num_vertices;j++)
10153 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10154 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10158 R_Mesh_PrepareVertices_Generic_Unlock();
10163 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10166 RSurf_SetupDepthAndCulling();
10167 if (r_showsurfaces.integer)
10169 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10172 switch (vid.renderpath)
10174 case RENDERPATH_GL20:
10175 case RENDERPATH_D3D9:
10176 case RENDERPATH_D3D10:
10177 case RENDERPATH_D3D11:
10178 case RENDERPATH_SOFT:
10179 case RENDERPATH_GLES2:
10180 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10182 case RENDERPATH_GL13:
10183 case RENDERPATH_GLES1:
10184 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10186 case RENDERPATH_GL11:
10187 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10193 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10196 RSurf_SetupDepthAndCulling();
10197 if (r_showsurfaces.integer)
10199 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10202 switch (vid.renderpath)
10204 case RENDERPATH_GL20:
10205 case RENDERPATH_D3D9:
10206 case RENDERPATH_D3D10:
10207 case RENDERPATH_D3D11:
10208 case RENDERPATH_SOFT:
10209 case RENDERPATH_GLES2:
10210 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10212 case RENDERPATH_GL13:
10213 case RENDERPATH_GLES1:
10214 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10216 case RENDERPATH_GL11:
10217 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10223 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10226 int texturenumsurfaces, endsurface;
10227 texture_t *texture;
10228 const msurface_t *surface;
10229 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10231 // if the model is static it doesn't matter what value we give for
10232 // wantnormals and wanttangents, so this logic uses only rules applicable
10233 // to a model, knowing that they are meaningless otherwise
10234 if (ent == r_refdef.scene.worldentity)
10235 RSurf_ActiveWorldEntity();
10236 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10237 RSurf_ActiveModelEntity(ent, false, false, false);
10240 switch (vid.renderpath)
10242 case RENDERPATH_GL20:
10243 case RENDERPATH_D3D9:
10244 case RENDERPATH_D3D10:
10245 case RENDERPATH_D3D11:
10246 case RENDERPATH_SOFT:
10247 case RENDERPATH_GLES2:
10248 RSurf_ActiveModelEntity(ent, true, true, false);
10250 case RENDERPATH_GL11:
10251 case RENDERPATH_GL13:
10252 case RENDERPATH_GLES1:
10253 RSurf_ActiveModelEntity(ent, true, false, false);
10258 if (r_transparentdepthmasking.integer)
10260 qboolean setup = false;
10261 for (i = 0;i < numsurfaces;i = j)
10264 surface = rsurface.modelsurfaces + surfacelist[i];
10265 texture = surface->texture;
10266 rsurface.texture = R_GetCurrentTexture(texture);
10267 rsurface.lightmaptexture = NULL;
10268 rsurface.deluxemaptexture = NULL;
10269 rsurface.uselightmaptexture = false;
10270 // scan ahead until we find a different texture
10271 endsurface = min(i + 1024, numsurfaces);
10272 texturenumsurfaces = 0;
10273 texturesurfacelist[texturenumsurfaces++] = surface;
10274 for (;j < endsurface;j++)
10276 surface = rsurface.modelsurfaces + surfacelist[j];
10277 if (texture != surface->texture)
10279 texturesurfacelist[texturenumsurfaces++] = surface;
10281 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10283 // render the range of surfaces as depth
10287 GL_ColorMask(0,0,0,0);
10289 GL_DepthTest(true);
10290 GL_BlendFunc(GL_ONE, GL_ZERO);
10291 GL_DepthMask(true);
10292 // R_Mesh_ResetTextureState();
10293 R_SetupShader_DepthOrShadow(false);
10295 RSurf_SetupDepthAndCulling();
10296 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10297 if (rsurface.batchvertex3fbuffer)
10298 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10300 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10304 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10307 for (i = 0;i < numsurfaces;i = j)
10310 surface = rsurface.modelsurfaces + surfacelist[i];
10311 texture = surface->texture;
10312 rsurface.texture = R_GetCurrentTexture(texture);
10313 // scan ahead until we find a different texture
10314 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10315 texturenumsurfaces = 0;
10316 texturesurfacelist[texturenumsurfaces++] = surface;
10317 if(FAKELIGHT_ENABLED)
10319 rsurface.lightmaptexture = NULL;
10320 rsurface.deluxemaptexture = NULL;
10321 rsurface.uselightmaptexture = false;
10322 for (;j < endsurface;j++)
10324 surface = rsurface.modelsurfaces + surfacelist[j];
10325 if (texture != surface->texture)
10327 texturesurfacelist[texturenumsurfaces++] = surface;
10332 rsurface.lightmaptexture = surface->lightmaptexture;
10333 rsurface.deluxemaptexture = surface->deluxemaptexture;
10334 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10335 for (;j < endsurface;j++)
10337 surface = rsurface.modelsurfaces + surfacelist[j];
10338 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10340 texturesurfacelist[texturenumsurfaces++] = surface;
10343 // render the range of surfaces
10344 if (ent == r_refdef.scene.worldentity)
10345 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10347 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10349 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10352 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10354 // transparent surfaces get pushed off into the transparent queue
10355 int surfacelistindex;
10356 const msurface_t *surface;
10357 vec3_t tempcenter, center;
10358 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10360 surface = texturesurfacelist[surfacelistindex];
10361 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10362 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10363 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10364 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10365 if (queueentity->transparent_offset) // transparent offset
10367 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10368 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10369 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10371 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10375 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10377 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10379 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10381 RSurf_SetupDepthAndCulling();
10382 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10383 if (rsurface.batchvertex3fbuffer)
10384 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10386 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10390 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10392 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10395 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10398 if (!rsurface.texture->currentnumlayers)
10400 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10401 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10403 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10405 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10406 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10407 else if (!rsurface.texture->currentnumlayers)
10409 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10411 // in the deferred case, transparent surfaces were queued during prepass
10412 if (!r_shadow_usingdeferredprepass)
10413 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10417 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10418 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10423 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10426 texture_t *texture;
10427 R_FrameData_SetMark();
10428 // break the surface list down into batches by texture and use of lightmapping
10429 for (i = 0;i < numsurfaces;i = j)
10432 // texture is the base texture pointer, rsurface.texture is the
10433 // current frame/skin the texture is directing us to use (for example
10434 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10435 // use skin 1 instead)
10436 texture = surfacelist[i]->texture;
10437 rsurface.texture = R_GetCurrentTexture(texture);
10438 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10440 // if this texture is not the kind we want, skip ahead to the next one
10441 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10445 if(FAKELIGHT_ENABLED || depthonly || prepass)
10447 rsurface.lightmaptexture = NULL;
10448 rsurface.deluxemaptexture = NULL;
10449 rsurface.uselightmaptexture = false;
10450 // simply scan ahead until we find a different texture or lightmap state
10451 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10456 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10457 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10458 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10459 // simply scan ahead until we find a different texture or lightmap state
10460 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10463 // render the range of surfaces
10464 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10466 R_FrameData_ReturnToMark();
10469 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10473 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10476 if (!rsurface.texture->currentnumlayers)
10478 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10479 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10481 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10483 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10484 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10485 else if (!rsurface.texture->currentnumlayers)
10487 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10489 // in the deferred case, transparent surfaces were queued during prepass
10490 if (!r_shadow_usingdeferredprepass)
10491 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10495 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10496 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10501 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10504 texture_t *texture;
10505 R_FrameData_SetMark();
10506 // break the surface list down into batches by texture and use of lightmapping
10507 for (i = 0;i < numsurfaces;i = j)
10510 // texture is the base texture pointer, rsurface.texture is the
10511 // current frame/skin the texture is directing us to use (for example
10512 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10513 // use skin 1 instead)
10514 texture = surfacelist[i]->texture;
10515 rsurface.texture = R_GetCurrentTexture(texture);
10516 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10518 // if this texture is not the kind we want, skip ahead to the next one
10519 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10523 if(FAKELIGHT_ENABLED || depthonly || prepass)
10525 rsurface.lightmaptexture = NULL;
10526 rsurface.deluxemaptexture = NULL;
10527 rsurface.uselightmaptexture = false;
10528 // simply scan ahead until we find a different texture or lightmap state
10529 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10534 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10535 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10536 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10537 // simply scan ahead until we find a different texture or lightmap state
10538 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10541 // render the range of surfaces
10542 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10544 R_FrameData_ReturnToMark();
10547 float locboxvertex3f[6*4*3] =
10549 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10550 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10551 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10552 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10553 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10554 1,0,0, 0,0,0, 0,1,0, 1,1,0
10557 unsigned short locboxelements[6*2*3] =
10562 12,13,14, 12,14,15,
10563 16,17,18, 16,18,19,
10567 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10570 cl_locnode_t *loc = (cl_locnode_t *)ent;
10572 float vertex3f[6*4*3];
10574 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10575 GL_DepthMask(false);
10576 GL_DepthRange(0, 1);
10577 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10578 GL_DepthTest(true);
10579 GL_CullFace(GL_NONE);
10580 R_EntityMatrix(&identitymatrix);
10582 // R_Mesh_ResetTextureState();
10584 i = surfacelist[0];
10585 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10586 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10587 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10588 surfacelist[0] < 0 ? 0.5f : 0.125f);
10590 if (VectorCompare(loc->mins, loc->maxs))
10592 VectorSet(size, 2, 2, 2);
10593 VectorMA(loc->mins, -0.5f, size, mins);
10597 VectorCopy(loc->mins, mins);
10598 VectorSubtract(loc->maxs, loc->mins, size);
10601 for (i = 0;i < 6*4*3;)
10602 for (j = 0;j < 3;j++, i++)
10603 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10605 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10606 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10607 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10610 void R_DrawLocs(void)
10613 cl_locnode_t *loc, *nearestloc;
10615 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10616 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10618 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10619 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10623 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10625 if (decalsystem->decals)
10626 Mem_Free(decalsystem->decals);
10627 memset(decalsystem, 0, sizeof(*decalsystem));
10630 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)
10633 tridecal_t *decals;
10636 // expand or initialize the system
10637 if (decalsystem->maxdecals <= decalsystem->numdecals)
10639 decalsystem_t old = *decalsystem;
10640 qboolean useshortelements;
10641 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10642 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10643 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)));
10644 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10645 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10646 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10647 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10648 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10649 if (decalsystem->numdecals)
10650 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10652 Mem_Free(old.decals);
10653 for (i = 0;i < decalsystem->maxdecals*3;i++)
10654 decalsystem->element3i[i] = i;
10655 if (useshortelements)
10656 for (i = 0;i < decalsystem->maxdecals*3;i++)
10657 decalsystem->element3s[i] = i;
10660 // grab a decal and search for another free slot for the next one
10661 decals = decalsystem->decals;
10662 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10663 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10665 decalsystem->freedecal = i;
10666 if (decalsystem->numdecals <= i)
10667 decalsystem->numdecals = i + 1;
10669 // initialize the decal
10671 decal->triangleindex = triangleindex;
10672 decal->surfaceindex = surfaceindex;
10673 decal->decalsequence = decalsequence;
10674 decal->color4f[0][0] = c0[0];
10675 decal->color4f[0][1] = c0[1];
10676 decal->color4f[0][2] = c0[2];
10677 decal->color4f[0][3] = 1;
10678 decal->color4f[1][0] = c1[0];
10679 decal->color4f[1][1] = c1[1];
10680 decal->color4f[1][2] = c1[2];
10681 decal->color4f[1][3] = 1;
10682 decal->color4f[2][0] = c2[0];
10683 decal->color4f[2][1] = c2[1];
10684 decal->color4f[2][2] = c2[2];
10685 decal->color4f[2][3] = 1;
10686 decal->vertex3f[0][0] = v0[0];
10687 decal->vertex3f[0][1] = v0[1];
10688 decal->vertex3f[0][2] = v0[2];
10689 decal->vertex3f[1][0] = v1[0];
10690 decal->vertex3f[1][1] = v1[1];
10691 decal->vertex3f[1][2] = v1[2];
10692 decal->vertex3f[2][0] = v2[0];
10693 decal->vertex3f[2][1] = v2[1];
10694 decal->vertex3f[2][2] = v2[2];
10695 decal->texcoord2f[0][0] = t0[0];
10696 decal->texcoord2f[0][1] = t0[1];
10697 decal->texcoord2f[1][0] = t1[0];
10698 decal->texcoord2f[1][1] = t1[1];
10699 decal->texcoord2f[2][0] = t2[0];
10700 decal->texcoord2f[2][1] = t2[1];
10701 TriangleNormal(v0, v1, v2, decal->plane);
10702 VectorNormalize(decal->plane);
10703 decal->plane[3] = DotProduct(v0, decal->plane);
10706 extern cvar_t cl_decals_bias;
10707 extern cvar_t cl_decals_models;
10708 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10709 // baseparms, parms, temps
10710 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)
10715 const float *vertex3f;
10716 const float *normal3f;
10718 float points[2][9][3];
10725 e = rsurface.modelelement3i + 3*triangleindex;
10727 vertex3f = rsurface.modelvertex3f;
10728 normal3f = rsurface.modelnormal3f;
10732 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10734 index = 3*e[cornerindex];
10735 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10740 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10742 index = 3*e[cornerindex];
10743 VectorCopy(vertex3f + index, v[cornerindex]);
10748 //TriangleNormal(v[0], v[1], v[2], normal);
10749 //if (DotProduct(normal, localnormal) < 0.0f)
10751 // clip by each of the box planes formed from the projection matrix
10752 // if anything survives, we emit the decal
10753 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]);
10756 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]);
10759 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]);
10762 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]);
10765 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]);
10768 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]);
10771 // some part of the triangle survived, so we have to accept it...
10774 // dynamic always uses the original triangle
10776 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10778 index = 3*e[cornerindex];
10779 VectorCopy(vertex3f + index, v[cornerindex]);
10782 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10784 // convert vertex positions to texcoords
10785 Matrix4x4_Transform(projection, v[cornerindex], temp);
10786 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10787 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10788 // calculate distance fade from the projection origin
10789 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10790 f = bound(0.0f, f, 1.0f);
10791 c[cornerindex][0] = r * f;
10792 c[cornerindex][1] = g * f;
10793 c[cornerindex][2] = b * f;
10794 c[cornerindex][3] = 1.0f;
10795 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10798 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);
10800 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10801 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);
10803 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)
10805 matrix4x4_t projection;
10806 decalsystem_t *decalsystem;
10809 const msurface_t *surface;
10810 const msurface_t *surfaces;
10811 const int *surfacelist;
10812 const texture_t *texture;
10814 int numsurfacelist;
10815 int surfacelistindex;
10818 float localorigin[3];
10819 float localnormal[3];
10820 float localmins[3];
10821 float localmaxs[3];
10824 float planes[6][4];
10827 int bih_triangles_count;
10828 int bih_triangles[256];
10829 int bih_surfaces[256];
10831 decalsystem = &ent->decalsystem;
10832 model = ent->model;
10833 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10835 R_DecalSystem_Reset(&ent->decalsystem);
10839 if (!model->brush.data_leafs && !cl_decals_models.integer)
10841 if (decalsystem->model)
10842 R_DecalSystem_Reset(decalsystem);
10846 if (decalsystem->model != model)
10847 R_DecalSystem_Reset(decalsystem);
10848 decalsystem->model = model;
10850 RSurf_ActiveModelEntity(ent, true, false, false);
10852 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10853 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10854 VectorNormalize(localnormal);
10855 localsize = worldsize*rsurface.inversematrixscale;
10856 localmins[0] = localorigin[0] - localsize;
10857 localmins[1] = localorigin[1] - localsize;
10858 localmins[2] = localorigin[2] - localsize;
10859 localmaxs[0] = localorigin[0] + localsize;
10860 localmaxs[1] = localorigin[1] + localsize;
10861 localmaxs[2] = localorigin[2] + localsize;
10863 //VectorCopy(localnormal, planes[4]);
10864 //VectorVectors(planes[4], planes[2], planes[0]);
10865 AnglesFromVectors(angles, localnormal, NULL, false);
10866 AngleVectors(angles, planes[0], planes[2], planes[4]);
10867 VectorNegate(planes[0], planes[1]);
10868 VectorNegate(planes[2], planes[3]);
10869 VectorNegate(planes[4], planes[5]);
10870 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10871 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10872 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10873 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10874 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10875 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10880 matrix4x4_t forwardprojection;
10881 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10882 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10887 float projectionvector[4][3];
10888 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10889 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10890 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10891 projectionvector[0][0] = planes[0][0] * ilocalsize;
10892 projectionvector[0][1] = planes[1][0] * ilocalsize;
10893 projectionvector[0][2] = planes[2][0] * ilocalsize;
10894 projectionvector[1][0] = planes[0][1] * ilocalsize;
10895 projectionvector[1][1] = planes[1][1] * ilocalsize;
10896 projectionvector[1][2] = planes[2][1] * ilocalsize;
10897 projectionvector[2][0] = planes[0][2] * ilocalsize;
10898 projectionvector[2][1] = planes[1][2] * ilocalsize;
10899 projectionvector[2][2] = planes[2][2] * ilocalsize;
10900 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10901 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10902 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10903 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10907 dynamic = model->surfmesh.isanimated;
10908 numsurfacelist = model->nummodelsurfaces;
10909 surfacelist = model->sortedmodelsurfaces;
10910 surfaces = model->data_surfaces;
10913 bih_triangles_count = -1;
10916 if(model->render_bih.numleafs)
10917 bih = &model->render_bih;
10918 else if(model->collision_bih.numleafs)
10919 bih = &model->collision_bih;
10922 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10923 if(bih_triangles_count == 0)
10925 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10927 if(bih_triangles_count > 0)
10929 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10931 surfaceindex = bih_surfaces[triangleindex];
10932 surface = surfaces + surfaceindex;
10933 texture = surface->texture;
10934 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10936 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10938 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10943 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10945 surfaceindex = surfacelist[surfacelistindex];
10946 surface = surfaces + surfaceindex;
10947 // check cull box first because it rejects more than any other check
10948 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10950 // skip transparent surfaces
10951 texture = surface->texture;
10952 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10954 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10956 numtriangles = surface->num_triangles;
10957 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10958 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10963 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10964 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)
10966 int renderentityindex;
10967 float worldmins[3];
10968 float worldmaxs[3];
10969 entity_render_t *ent;
10971 if (!cl_decals_newsystem.integer)
10974 worldmins[0] = worldorigin[0] - worldsize;
10975 worldmins[1] = worldorigin[1] - worldsize;
10976 worldmins[2] = worldorigin[2] - worldsize;
10977 worldmaxs[0] = worldorigin[0] + worldsize;
10978 worldmaxs[1] = worldorigin[1] + worldsize;
10979 worldmaxs[2] = worldorigin[2] + worldsize;
10981 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10983 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10985 ent = r_refdef.scene.entities[renderentityindex];
10986 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10989 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10993 typedef struct r_decalsystem_splatqueue_s
10995 vec3_t worldorigin;
10996 vec3_t worldnormal;
11002 r_decalsystem_splatqueue_t;
11004 int r_decalsystem_numqueued = 0;
11005 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11007 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)
11009 r_decalsystem_splatqueue_t *queue;
11011 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11014 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11015 VectorCopy(worldorigin, queue->worldorigin);
11016 VectorCopy(worldnormal, queue->worldnormal);
11017 Vector4Set(queue->color, r, g, b, a);
11018 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11019 queue->worldsize = worldsize;
11020 queue->decalsequence = cl.decalsequence++;
11023 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11026 r_decalsystem_splatqueue_t *queue;
11028 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11029 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);
11030 r_decalsystem_numqueued = 0;
11033 extern cvar_t cl_decals_max;
11034 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11037 decalsystem_t *decalsystem = &ent->decalsystem;
11044 if (!decalsystem->numdecals)
11047 if (r_showsurfaces.integer)
11050 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11052 R_DecalSystem_Reset(decalsystem);
11056 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11057 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11059 if (decalsystem->lastupdatetime)
11060 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11063 decalsystem->lastupdatetime = r_refdef.scene.time;
11064 decal = decalsystem->decals;
11065 numdecals = decalsystem->numdecals;
11067 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11069 if (decal->color4f[0][3])
11071 decal->lived += frametime;
11072 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11074 memset(decal, 0, sizeof(*decal));
11075 if (decalsystem->freedecal > i)
11076 decalsystem->freedecal = i;
11080 decal = decalsystem->decals;
11081 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11084 // collapse the array by shuffling the tail decals into the gaps
11087 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11088 decalsystem->freedecal++;
11089 if (decalsystem->freedecal == numdecals)
11091 decal[decalsystem->freedecal] = decal[--numdecals];
11094 decalsystem->numdecals = numdecals;
11096 if (numdecals <= 0)
11098 // if there are no decals left, reset decalsystem
11099 R_DecalSystem_Reset(decalsystem);
11103 extern skinframe_t *decalskinframe;
11104 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11107 decalsystem_t *decalsystem = &ent->decalsystem;
11116 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11119 numdecals = decalsystem->numdecals;
11123 if (r_showsurfaces.integer)
11126 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11128 R_DecalSystem_Reset(decalsystem);
11132 // if the model is static it doesn't matter what value we give for
11133 // wantnormals and wanttangents, so this logic uses only rules applicable
11134 // to a model, knowing that they are meaningless otherwise
11135 if (ent == r_refdef.scene.worldentity)
11136 RSurf_ActiveWorldEntity();
11138 RSurf_ActiveModelEntity(ent, false, false, false);
11140 decalsystem->lastupdatetime = r_refdef.scene.time;
11141 decal = decalsystem->decals;
11143 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11145 // update vertex positions for animated models
11146 v3f = decalsystem->vertex3f;
11147 c4f = decalsystem->color4f;
11148 t2f = decalsystem->texcoord2f;
11149 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11151 if (!decal->color4f[0][3])
11154 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11158 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11161 // update color values for fading decals
11162 if (decal->lived >= cl_decals_time.value)
11163 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11167 c4f[ 0] = decal->color4f[0][0] * alpha;
11168 c4f[ 1] = decal->color4f[0][1] * alpha;
11169 c4f[ 2] = decal->color4f[0][2] * alpha;
11171 c4f[ 4] = decal->color4f[1][0] * alpha;
11172 c4f[ 5] = decal->color4f[1][1] * alpha;
11173 c4f[ 6] = decal->color4f[1][2] * alpha;
11175 c4f[ 8] = decal->color4f[2][0] * alpha;
11176 c4f[ 9] = decal->color4f[2][1] * alpha;
11177 c4f[10] = decal->color4f[2][2] * alpha;
11180 t2f[0] = decal->texcoord2f[0][0];
11181 t2f[1] = decal->texcoord2f[0][1];
11182 t2f[2] = decal->texcoord2f[1][0];
11183 t2f[3] = decal->texcoord2f[1][1];
11184 t2f[4] = decal->texcoord2f[2][0];
11185 t2f[5] = decal->texcoord2f[2][1];
11187 // update vertex positions for animated models
11188 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11190 e = rsurface.modelelement3i + 3*decal->triangleindex;
11191 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11192 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11193 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11197 VectorCopy(decal->vertex3f[0], v3f);
11198 VectorCopy(decal->vertex3f[1], v3f + 3);
11199 VectorCopy(decal->vertex3f[2], v3f + 6);
11202 if (r_refdef.fogenabled)
11204 alpha = RSurf_FogVertex(v3f);
11205 VectorScale(c4f, alpha, c4f);
11206 alpha = RSurf_FogVertex(v3f + 3);
11207 VectorScale(c4f + 4, alpha, c4f + 4);
11208 alpha = RSurf_FogVertex(v3f + 6);
11209 VectorScale(c4f + 8, alpha, c4f + 8);
11220 r_refdef.stats.drawndecals += numtris;
11222 // now render the decals all at once
11223 // (this assumes they all use one particle font texture!)
11224 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);
11225 // R_Mesh_ResetTextureState();
11226 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11227 GL_DepthMask(false);
11228 GL_DepthRange(0, 1);
11229 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11230 GL_DepthTest(true);
11231 GL_CullFace(GL_NONE);
11232 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11233 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11234 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11238 static void R_DrawModelDecals(void)
11242 // fade faster when there are too many decals
11243 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11244 for (i = 0;i < r_refdef.scene.numentities;i++)
11245 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11247 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11248 for (i = 0;i < r_refdef.scene.numentities;i++)
11249 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11250 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11252 R_DecalSystem_ApplySplatEntitiesQueue();
11254 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11255 for (i = 0;i < r_refdef.scene.numentities;i++)
11256 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11258 r_refdef.stats.totaldecals += numdecals;
11260 if (r_showsurfaces.integer)
11263 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11265 for (i = 0;i < r_refdef.scene.numentities;i++)
11267 if (!r_refdef.viewcache.entityvisible[i])
11269 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11270 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11274 extern cvar_t mod_collision_bih;
11275 void R_DrawDebugModel(void)
11277 entity_render_t *ent = rsurface.entity;
11278 int i, j, k, l, flagsmask;
11279 const msurface_t *surface;
11280 dp_model_t *model = ent->model;
11283 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11286 if (r_showoverdraw.value > 0)
11288 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11289 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11290 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11291 GL_DepthTest(false);
11292 GL_DepthMask(false);
11293 GL_DepthRange(0, 1);
11294 GL_BlendFunc(GL_ONE, GL_ONE);
11295 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11297 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11299 rsurface.texture = R_GetCurrentTexture(surface->texture);
11300 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11302 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11303 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11304 if (!rsurface.texture->currentlayers->depthmask)
11305 GL_Color(c, 0, 0, 1.0f);
11306 else if (ent == r_refdef.scene.worldentity)
11307 GL_Color(c, c, c, 1.0f);
11309 GL_Color(0, c, 0, 1.0f);
11310 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11314 rsurface.texture = NULL;
11317 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11319 // R_Mesh_ResetTextureState();
11320 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11321 GL_DepthRange(0, 1);
11322 GL_DepthTest(!r_showdisabledepthtest.integer);
11323 GL_DepthMask(false);
11324 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11326 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11330 qboolean cullbox = ent == r_refdef.scene.worldentity;
11331 const q3mbrush_t *brush;
11332 const bih_t *bih = &model->collision_bih;
11333 const bih_leaf_t *bihleaf;
11334 float vertex3f[3][3];
11335 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11337 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11339 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11341 switch (bihleaf->type)
11344 brush = model->brush.data_brushes + bihleaf->itemindex;
11345 if (brush->colbrushf && brush->colbrushf->numtriangles)
11347 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);
11348 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11349 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11352 case BIH_COLLISIONTRIANGLE:
11353 triangleindex = bihleaf->itemindex;
11354 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11355 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11356 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11357 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);
11358 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11359 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11361 case BIH_RENDERTRIANGLE:
11362 triangleindex = bihleaf->itemindex;
11363 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11364 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11365 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11366 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);
11367 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11368 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11374 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11377 if (r_showtris.integer && qglPolygonMode)
11379 if (r_showdisabledepthtest.integer)
11381 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11382 GL_DepthMask(false);
11386 GL_BlendFunc(GL_ONE, GL_ZERO);
11387 GL_DepthMask(true);
11389 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11390 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11392 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11394 rsurface.texture = R_GetCurrentTexture(surface->texture);
11395 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11397 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11398 if (!rsurface.texture->currentlayers->depthmask)
11399 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11400 else if (ent == r_refdef.scene.worldentity)
11401 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11403 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11404 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11408 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11409 rsurface.texture = NULL;
11412 if (r_shownormals.value != 0 && qglBegin)
11414 if (r_showdisabledepthtest.integer)
11416 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11417 GL_DepthMask(false);
11421 GL_BlendFunc(GL_ONE, GL_ZERO);
11422 GL_DepthMask(true);
11424 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11426 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11428 rsurface.texture = R_GetCurrentTexture(surface->texture);
11429 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11431 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11432 qglBegin(GL_LINES);
11433 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11435 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11437 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11438 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11439 qglVertex3f(v[0], v[1], v[2]);
11440 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11441 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11442 qglVertex3f(v[0], v[1], v[2]);
11445 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11447 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11449 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11450 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11451 qglVertex3f(v[0], v[1], v[2]);
11452 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11453 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11454 qglVertex3f(v[0], v[1], v[2]);
11457 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11459 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11461 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11462 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11463 qglVertex3f(v[0], v[1], v[2]);
11464 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11465 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11466 qglVertex3f(v[0], v[1], v[2]);
11469 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11471 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11473 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11474 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11475 qglVertex3f(v[0], v[1], v[2]);
11476 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11477 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11478 qglVertex3f(v[0], v[1], v[2]);
11485 rsurface.texture = NULL;
11490 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11491 int r_maxsurfacelist = 0;
11492 const msurface_t **r_surfacelist = NULL;
11493 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11495 int i, j, endj, flagsmask;
11496 dp_model_t *model = r_refdef.scene.worldmodel;
11497 msurface_t *surfaces;
11498 unsigned char *update;
11499 int numsurfacelist = 0;
11503 if (r_maxsurfacelist < model->num_surfaces)
11505 r_maxsurfacelist = model->num_surfaces;
11507 Mem_Free((msurface_t**)r_surfacelist);
11508 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11511 RSurf_ActiveWorldEntity();
11513 surfaces = model->data_surfaces;
11514 update = model->brushq1.lightmapupdateflags;
11516 // update light styles on this submodel
11517 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11519 model_brush_lightstyleinfo_t *style;
11520 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11522 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11524 int *list = style->surfacelist;
11525 style->value = r_refdef.scene.lightstylevalue[style->style];
11526 for (j = 0;j < style->numsurfaces;j++)
11527 update[list[j]] = true;
11532 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11536 R_DrawDebugModel();
11537 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11541 rsurface.lightmaptexture = NULL;
11542 rsurface.deluxemaptexture = NULL;
11543 rsurface.uselightmaptexture = false;
11544 rsurface.texture = NULL;
11545 rsurface.rtlight = NULL;
11546 numsurfacelist = 0;
11547 // add visible surfaces to draw list
11548 for (i = 0;i < model->nummodelsurfaces;i++)
11550 j = model->sortedmodelsurfaces[i];
11551 if (r_refdef.viewcache.world_surfacevisible[j])
11552 r_surfacelist[numsurfacelist++] = surfaces + j;
11554 // update lightmaps if needed
11555 if (model->brushq1.firstrender)
11557 model->brushq1.firstrender = false;
11558 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11560 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11564 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11565 if (r_refdef.viewcache.world_surfacevisible[j])
11567 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11569 // don't do anything if there were no surfaces
11570 if (!numsurfacelist)
11572 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11575 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11577 // add to stats if desired
11578 if (r_speeds.integer && !skysurfaces && !depthonly)
11580 r_refdef.stats.world_surfaces += numsurfacelist;
11581 for (j = 0;j < numsurfacelist;j++)
11582 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11585 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11588 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11590 int i, j, endj, flagsmask;
11591 dp_model_t *model = ent->model;
11592 msurface_t *surfaces;
11593 unsigned char *update;
11594 int numsurfacelist = 0;
11598 if (r_maxsurfacelist < model->num_surfaces)
11600 r_maxsurfacelist = model->num_surfaces;
11602 Mem_Free((msurface_t **)r_surfacelist);
11603 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11606 // if the model is static it doesn't matter what value we give for
11607 // wantnormals and wanttangents, so this logic uses only rules applicable
11608 // to a model, knowing that they are meaningless otherwise
11609 if (ent == r_refdef.scene.worldentity)
11610 RSurf_ActiveWorldEntity();
11611 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11612 RSurf_ActiveModelEntity(ent, false, false, false);
11614 RSurf_ActiveModelEntity(ent, true, true, true);
11615 else if (depthonly)
11617 switch (vid.renderpath)
11619 case RENDERPATH_GL20:
11620 case RENDERPATH_D3D9:
11621 case RENDERPATH_D3D10:
11622 case RENDERPATH_D3D11:
11623 case RENDERPATH_SOFT:
11624 case RENDERPATH_GLES2:
11625 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11627 case RENDERPATH_GL11:
11628 case RENDERPATH_GL13:
11629 case RENDERPATH_GLES1:
11630 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11636 switch (vid.renderpath)
11638 case RENDERPATH_GL20:
11639 case RENDERPATH_D3D9:
11640 case RENDERPATH_D3D10:
11641 case RENDERPATH_D3D11:
11642 case RENDERPATH_SOFT:
11643 case RENDERPATH_GLES2:
11644 RSurf_ActiveModelEntity(ent, true, true, false);
11646 case RENDERPATH_GL11:
11647 case RENDERPATH_GL13:
11648 case RENDERPATH_GLES1:
11649 RSurf_ActiveModelEntity(ent, true, false, false);
11654 surfaces = model->data_surfaces;
11655 update = model->brushq1.lightmapupdateflags;
11657 // update light styles
11658 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11660 model_brush_lightstyleinfo_t *style;
11661 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11663 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11665 int *list = style->surfacelist;
11666 style->value = r_refdef.scene.lightstylevalue[style->style];
11667 for (j = 0;j < style->numsurfaces;j++)
11668 update[list[j]] = true;
11673 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11677 R_DrawDebugModel();
11678 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11682 rsurface.lightmaptexture = NULL;
11683 rsurface.deluxemaptexture = NULL;
11684 rsurface.uselightmaptexture = false;
11685 rsurface.texture = NULL;
11686 rsurface.rtlight = NULL;
11687 numsurfacelist = 0;
11688 // add visible surfaces to draw list
11689 for (i = 0;i < model->nummodelsurfaces;i++)
11690 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11691 // don't do anything if there were no surfaces
11692 if (!numsurfacelist)
11694 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11697 // update lightmaps if needed
11701 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11706 R_BuildLightMap(ent, surfaces + j);
11711 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11713 R_BuildLightMap(ent, surfaces + j);
11714 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11716 // add to stats if desired
11717 if (r_speeds.integer && !skysurfaces && !depthonly)
11719 r_refdef.stats.entities_surfaces += numsurfacelist;
11720 for (j = 0;j < numsurfacelist;j++)
11721 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11724 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11727 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11729 static texture_t texture;
11730 static msurface_t surface;
11731 const msurface_t *surfacelist = &surface;
11733 // fake enough texture and surface state to render this geometry
11735 texture.update_lastrenderframe = -1; // regenerate this texture
11736 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11737 texture.currentskinframe = skinframe;
11738 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11739 texture.offsetmapping = OFFSETMAPPING_OFF;
11740 texture.offsetscale = 1;
11741 texture.specularscalemod = 1;
11742 texture.specularpowermod = 1;
11744 surface.texture = &texture;
11745 surface.num_triangles = numtriangles;
11746 surface.num_firsttriangle = firsttriangle;
11747 surface.num_vertices = numvertices;
11748 surface.num_firstvertex = firstvertex;
11751 rsurface.texture = R_GetCurrentTexture(surface.texture);
11752 rsurface.lightmaptexture = NULL;
11753 rsurface.deluxemaptexture = NULL;
11754 rsurface.uselightmaptexture = false;
11755 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11758 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)
11760 static msurface_t surface;
11761 const msurface_t *surfacelist = &surface;
11763 // fake enough texture and surface state to render this geometry
11764 surface.texture = texture;
11765 surface.num_triangles = numtriangles;
11766 surface.num_firsttriangle = firsttriangle;
11767 surface.num_vertices = numvertices;
11768 surface.num_firstvertex = firstvertex;
11771 rsurface.texture = R_GetCurrentTexture(surface.texture);
11772 rsurface.lightmaptexture = NULL;
11773 rsurface.deluxemaptexture = NULL;
11774 rsurface.uselightmaptexture = false;
11775 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);