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_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
130 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
132 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
133 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
134 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
135 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
136 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
137 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
138 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
139 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
141 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)"};
142 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"};
144 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
145 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
146 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
148 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"};
149 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"};
150 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
151 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
152 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"};
153 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)"};
154 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)"};
155 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
157 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)"};
158 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
159 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)"};
160 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
161 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)"};
162 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)"};
163 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
164 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
174 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)"};
175 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
176 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"};
177 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
178 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
179 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
180 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"};
182 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
183 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
184 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
185 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
187 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
188 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
189 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
190 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
191 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
192 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
193 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
195 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
196 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
197 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
198 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)"};
199 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
200 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
201 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
202 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
204 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
205 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
207 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"};
209 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"};
211 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
213 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
215 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
216 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"};
218 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."};
220 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)"};
222 extern cvar_t v_glslgamma;
224 extern qboolean v_flipped_state;
226 static struct r_bloomstate_s
231 int bloomwidth, bloomheight;
233 textype_t texturetype;
234 int viewfbo; // used to check if r_viewfbo cvar has changed
236 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
237 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
238 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
240 int screentexturewidth, screentextureheight;
241 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
243 int bloomtexturewidth, bloomtextureheight;
244 rtexture_t *texture_bloom;
246 // arrays for rendering the screen passes
247 float screentexcoord2f[8];
248 float bloomtexcoord2f[8];
249 float offsettexcoord2f[8];
251 r_viewport_t viewport;
255 r_waterstate_t r_waterstate;
257 /// shadow volume bsp struct with automatically growing nodes buffer
260 rtexture_t *r_texture_blanknormalmap;
261 rtexture_t *r_texture_white;
262 rtexture_t *r_texture_grey128;
263 rtexture_t *r_texture_black;
264 rtexture_t *r_texture_notexture;
265 rtexture_t *r_texture_whitecube;
266 rtexture_t *r_texture_normalizationcube;
267 rtexture_t *r_texture_fogattenuation;
268 rtexture_t *r_texture_fogheighttexture;
269 rtexture_t *r_texture_gammaramps;
270 unsigned int r_texture_gammaramps_serial;
271 //rtexture_t *r_texture_fogintensity;
272 rtexture_t *r_texture_reflectcube;
274 // TODO: hash lookups?
275 typedef struct cubemapinfo_s
282 int r_texture_numcubemaps;
283 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
285 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
286 unsigned int r_numqueries;
287 unsigned int r_maxqueries;
289 typedef struct r_qwskincache_s
291 char name[MAX_QPATH];
292 skinframe_t *skinframe;
296 static r_qwskincache_t *r_qwskincache;
297 static int r_qwskincache_size;
299 /// vertex coordinates for a quad that covers the screen exactly
300 extern const float r_screenvertex3f[12];
301 extern const float r_d3dscreenvertex3f[12];
302 const float r_screenvertex3f[12] =
309 const float r_d3dscreenvertex3f[12] =
317 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
320 for (i = 0;i < verts;i++)
331 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
334 for (i = 0;i < verts;i++)
344 // FIXME: move this to client?
347 if (gamemode == GAME_NEHAHRA)
349 Cvar_Set("gl_fogenable", "0");
350 Cvar_Set("gl_fogdensity", "0.2");
351 Cvar_Set("gl_fogred", "0.3");
352 Cvar_Set("gl_foggreen", "0.3");
353 Cvar_Set("gl_fogblue", "0.3");
355 r_refdef.fog_density = 0;
356 r_refdef.fog_red = 0;
357 r_refdef.fog_green = 0;
358 r_refdef.fog_blue = 0;
359 r_refdef.fog_alpha = 1;
360 r_refdef.fog_start = 0;
361 r_refdef.fog_end = 16384;
362 r_refdef.fog_height = 1<<30;
363 r_refdef.fog_fadedepth = 128;
364 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
367 static void R_BuildBlankTextures(void)
369 unsigned char data[4];
370 data[2] = 128; // normal X
371 data[1] = 128; // normal Y
372 data[0] = 255; // normal Z
373 data[3] = 128; // height
374 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
389 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 static void R_BuildNoTexture(void)
395 unsigned char pix[16][16][4];
396 // this makes a light grey/dark grey checkerboard texture
397 for (y = 0;y < 16;y++)
399 for (x = 0;x < 16;x++)
401 if ((y < 8) ^ (x < 8))
417 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
420 static void R_BuildWhiteCube(void)
422 unsigned char data[6*1*1*4];
423 memset(data, 255, sizeof(data));
424 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
427 static void R_BuildNormalizationCube(void)
431 vec_t s, t, intensity;
434 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
435 for (side = 0;side < 6;side++)
437 for (y = 0;y < NORMSIZE;y++)
439 for (x = 0;x < NORMSIZE;x++)
441 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
442 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
477 intensity = 127.0f / sqrt(DotProduct(v, v));
478 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
479 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
480 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
481 data[((side*64+y)*64+x)*4+3] = 255;
485 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
489 static void R_BuildFogTexture(void)
493 unsigned char data1[FOGWIDTH][4];
494 //unsigned char data2[FOGWIDTH][4];
497 r_refdef.fogmasktable_start = r_refdef.fog_start;
498 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
499 r_refdef.fogmasktable_range = r_refdef.fogrange;
500 r_refdef.fogmasktable_density = r_refdef.fog_density;
502 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
503 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505 d = (x * r - r_refdef.fogmasktable_start);
506 if(developer_extra.integer)
507 Con_DPrintf("%f ", d);
509 if (r_fog_exp2.integer)
510 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
513 if(developer_extra.integer)
514 Con_DPrintf(" : %f ", alpha);
515 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
516 if(developer_extra.integer)
517 Con_DPrintf(" = %f\n", alpha);
518 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
521 for (x = 0;x < FOGWIDTH;x++)
523 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
528 //data2[x][0] = 255 - b;
529 //data2[x][1] = 255 - b;
530 //data2[x][2] = 255 - b;
533 if (r_texture_fogattenuation)
535 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
536 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
540 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
541 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
545 static void R_BuildFogHeightTexture(void)
547 unsigned char *inpixels;
555 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
556 if (r_refdef.fogheighttexturename[0])
557 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
560 r_refdef.fog_height_tablesize = 0;
561 if (r_texture_fogheighttexture)
562 R_FreeTexture(r_texture_fogheighttexture);
563 r_texture_fogheighttexture = NULL;
564 if (r_refdef.fog_height_table2d)
565 Mem_Free(r_refdef.fog_height_table2d);
566 r_refdef.fog_height_table2d = NULL;
567 if (r_refdef.fog_height_table1d)
568 Mem_Free(r_refdef.fog_height_table1d);
569 r_refdef.fog_height_table1d = NULL;
573 r_refdef.fog_height_tablesize = size;
574 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
575 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
576 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578 // LordHavoc: now the magic - what is that table2d for? it is a cooked
579 // average fog color table accounting for every fog layer between a point
580 // and the camera. (Note: attenuation is handled separately!)
581 for (y = 0;y < size;y++)
583 for (x = 0;x < size;x++)
589 for (j = x;j <= y;j++)
591 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
597 for (j = x;j >= y;j--)
599 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
604 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
605 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
606 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
610 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
613 //=======================================================================================================================================================
615 static const char *builtinshaderstring =
616 #include "shader_glsl.h"
619 const char *builtinhlslshaderstring =
620 #include "shader_hlsl.h"
623 char *glslshaderstring = NULL;
624 char *hlslshaderstring = NULL;
626 //=======================================================================================================================================================
628 typedef struct shaderpermutationinfo_s
633 shaderpermutationinfo_t;
635 typedef struct shadermodeinfo_s
637 const char *vertexfilename;
638 const char *geometryfilename;
639 const char *fragmentfilename;
645 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
646 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
648 {"#define USEDIFFUSE\n", " diffuse"},
649 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
650 {"#define USEVIEWTINT\n", " viewtint"},
651 {"#define USECOLORMAPPING\n", " colormapping"},
652 {"#define USESATURATION\n", " saturation"},
653 {"#define USEFOGINSIDE\n", " foginside"},
654 {"#define USEFOGOUTSIDE\n", " fogoutside"},
655 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
656 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
657 {"#define USEGAMMARAMPS\n", " gammaramps"},
658 {"#define USECUBEFILTER\n", " cubefilter"},
659 {"#define USEGLOW\n", " glow"},
660 {"#define USEBLOOM\n", " bloom"},
661 {"#define USESPECULAR\n", " specular"},
662 {"#define USEPOSTPROCESSING\n", " postprocessing"},
663 {"#define USEREFLECTION\n", " reflection"},
664 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
665 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
666 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
667 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
668 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
669 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
670 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
671 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673 {"#define USEALPHAKILL\n", " alphakill"},
674 {"#define USEREFLECTCUBE\n", " reflectcube"},
675 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676 {"#define USEBOUNCEGRID\n", " bouncegrid"},
677 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
678 {"#define USETRIPPY\n", " trippy"},
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
726 struct r_glsl_permutation_s *hashnext;
728 unsigned int permutation;
730 /// indicates if we have tried compiling this permutation already
732 /// 0 if compilation failed
734 // texture units assigned to each detected uniform
735 int tex_Texture_First;
736 int tex_Texture_Second;
737 int tex_Texture_GammaRamps;
738 int tex_Texture_Normal;
739 int tex_Texture_Color;
740 int tex_Texture_Gloss;
741 int tex_Texture_Glow;
742 int tex_Texture_SecondaryNormal;
743 int tex_Texture_SecondaryColor;
744 int tex_Texture_SecondaryGloss;
745 int tex_Texture_SecondaryGlow;
746 int tex_Texture_Pants;
747 int tex_Texture_Shirt;
748 int tex_Texture_FogHeightTexture;
749 int tex_Texture_FogMask;
750 int tex_Texture_Lightmap;
751 int tex_Texture_Deluxemap;
752 int tex_Texture_Attenuation;
753 int tex_Texture_Cube;
754 int tex_Texture_Refraction;
755 int tex_Texture_Reflection;
756 int tex_Texture_ShadowMap2D;
757 int tex_Texture_CubeProjection;
758 int tex_Texture_ScreenDepth;
759 int tex_Texture_ScreenNormalMap;
760 int tex_Texture_ScreenDiffuse;
761 int tex_Texture_ScreenSpecular;
762 int tex_Texture_ReflectMask;
763 int tex_Texture_ReflectCube;
764 int tex_Texture_BounceGrid;
765 /// locations of detected uniforms in program object, or -1 if not found
766 int loc_Texture_First;
767 int loc_Texture_Second;
768 int loc_Texture_GammaRamps;
769 int loc_Texture_Normal;
770 int loc_Texture_Color;
771 int loc_Texture_Gloss;
772 int loc_Texture_Glow;
773 int loc_Texture_SecondaryNormal;
774 int loc_Texture_SecondaryColor;
775 int loc_Texture_SecondaryGloss;
776 int loc_Texture_SecondaryGlow;
777 int loc_Texture_Pants;
778 int loc_Texture_Shirt;
779 int loc_Texture_FogHeightTexture;
780 int loc_Texture_FogMask;
781 int loc_Texture_Lightmap;
782 int loc_Texture_Deluxemap;
783 int loc_Texture_Attenuation;
784 int loc_Texture_Cube;
785 int loc_Texture_Refraction;
786 int loc_Texture_Reflection;
787 int loc_Texture_ShadowMap2D;
788 int loc_Texture_CubeProjection;
789 int loc_Texture_ScreenDepth;
790 int loc_Texture_ScreenNormalMap;
791 int loc_Texture_ScreenDiffuse;
792 int loc_Texture_ScreenSpecular;
793 int loc_Texture_ReflectMask;
794 int loc_Texture_ReflectCube;
795 int loc_Texture_BounceGrid;
797 int loc_BloomBlur_Parameters;
799 int loc_Color_Ambient;
800 int loc_Color_Diffuse;
801 int loc_Color_Specular;
805 int loc_DeferredColor_Ambient;
806 int loc_DeferredColor_Diffuse;
807 int loc_DeferredColor_Specular;
808 int loc_DeferredMod_Diffuse;
809 int loc_DeferredMod_Specular;
810 int loc_DistortScaleRefractReflect;
813 int loc_FogHeightFade;
815 int loc_FogPlaneViewDist;
816 int loc_FogRangeRecip;
819 int loc_LightPosition;
820 int loc_OffsetMapping_ScaleSteps;
822 int loc_ReflectColor;
823 int loc_ReflectFactor;
824 int loc_ReflectOffset;
825 int loc_RefractColor;
827 int loc_ScreenCenterRefractReflect;
828 int loc_ScreenScaleRefractReflect;
829 int loc_ScreenToDepth;
830 int loc_ShadowMap_Parameters;
831 int loc_ShadowMap_TextureScale;
832 int loc_SpecularPower;
837 int loc_ViewTintColor;
839 int loc_ModelToLight;
841 int loc_BackgroundTexMatrix;
842 int loc_ModelViewProjectionMatrix;
843 int loc_ModelViewMatrix;
844 int loc_PixelToScreenTexCoord;
845 int loc_ModelToReflectCube;
846 int loc_ShadowMapMatrix;
847 int loc_BloomColorSubtract;
848 int loc_NormalmapScrollBlend;
849 int loc_BounceGridMatrix;
850 int loc_BounceGridIntensity;
852 r_glsl_permutation_t;
854 #define SHADERPERMUTATION_HASHSIZE 256
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
861 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
867 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
869 #define SHADERSTATICPARMS_COUNT 7
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
878 static int r_compileshader_staticparms_save[1];
879 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
883 if (r_glsl_saturation_redcompensate.integer)
884 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885 if (r_glsl_vertextextureblend_usebothalphas.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887 if (r_shadow_glossexact.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889 if (r_glsl_postprocess.integer)
891 if (r_glsl_postprocess_uservec1_enable.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893 if (r_glsl_postprocess_uservec2_enable.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895 if (r_glsl_postprocess_uservec3_enable.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897 if (r_glsl_postprocess_uservec4_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
900 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 shaderstaticparms_count = 0;
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
931 //unsigned int hashdepth = 0;
932 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933 r_glsl_permutation_t *p;
934 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
936 if (p->mode == mode && p->permutation == permutation)
938 //if (hashdepth > 10)
939 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
944 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
946 p->permutation = permutation;
947 p->hashnext = r_glsl_permutationhash[mode][hashindex];
948 r_glsl_permutationhash[mode][hashindex] = p;
949 //if (hashdepth > 10)
950 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
957 if (!filename || !filename[0])
959 if (!strcmp(filename, "glsl/default.glsl"))
961 if (!glslshaderstring)
963 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964 if (glslshaderstring)
965 Con_DPrintf("Loading shaders from file %s...\n", filename);
967 glslshaderstring = (char *)builtinshaderstring;
969 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
973 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
976 if (printfromdisknotice)
977 Con_DPrintf("from disk %s... ", filename);
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
987 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988 char *vertexstring, *geometrystring, *fragmentstring;
989 char permutationname[256];
990 int vertstrings_count = 0;
991 int geomstrings_count = 0;
992 int fragstrings_count = 0;
993 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002 permutationname[0] = 0;
1003 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1007 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1009 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010 if(vid.support.gl20shaders130)
1012 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1020 // the first pretext is which type of shader to compile as
1021 // (later these will all be bound together as a program object)
1022 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1026 // the second pretext is the mode (for example a light source)
1027 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1032 // now add all the permutation pretexts
1033 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1035 if (permutation & (1<<i))
1037 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1044 // keep line numbers correct
1045 vertstrings_list[vertstrings_count++] = "\n";
1046 geomstrings_list[geomstrings_count++] = "\n";
1047 fragstrings_list[fragstrings_count++] = "\n";
1052 R_CompileShader_AddStaticParms(mode, permutation);
1053 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054 vertstrings_count += shaderstaticparms_count;
1055 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056 geomstrings_count += shaderstaticparms_count;
1057 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058 fragstrings_count += shaderstaticparms_count;
1060 // now append the shader text itself
1061 vertstrings_list[vertstrings_count++] = vertexstring;
1062 geomstrings_list[geomstrings_count++] = geometrystring;
1063 fragstrings_list[fragstrings_count++] = fragmentstring;
1065 // if any sources were NULL, clear the respective list
1067 vertstrings_count = 0;
1068 if (!geometrystring)
1069 geomstrings_count = 0;
1070 if (!fragmentstring)
1071 fragstrings_count = 0;
1073 // compile the shader program
1074 if (vertstrings_count + geomstrings_count + fragstrings_count)
1075 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1079 qglUseProgram(p->program);CHECKGLERROR
1080 // look up all the uniform variable names we care about, so we don't
1081 // have to look them up every time we set them
1083 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1084 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1085 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1087 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1088 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1089 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1090 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1095 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1096 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1098 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1102 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1103 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1104 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1114 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1116 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1117 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1118 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1119 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1120 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1121 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1122 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1129 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1130 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1131 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1132 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1134 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1135 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1136 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1137 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1139 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1140 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1141 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1142 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1143 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1144 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1147 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1150 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1151 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1152 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1153 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1154 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1155 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1156 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1157 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1158 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168 // initialize the samplers to refer to the texture units we use
1169 p->tex_Texture_First = -1;
1170 p->tex_Texture_Second = -1;
1171 p->tex_Texture_GammaRamps = -1;
1172 p->tex_Texture_Normal = -1;
1173 p->tex_Texture_Color = -1;
1174 p->tex_Texture_Gloss = -1;
1175 p->tex_Texture_Glow = -1;
1176 p->tex_Texture_SecondaryNormal = -1;
1177 p->tex_Texture_SecondaryColor = -1;
1178 p->tex_Texture_SecondaryGloss = -1;
1179 p->tex_Texture_SecondaryGlow = -1;
1180 p->tex_Texture_Pants = -1;
1181 p->tex_Texture_Shirt = -1;
1182 p->tex_Texture_FogHeightTexture = -1;
1183 p->tex_Texture_FogMask = -1;
1184 p->tex_Texture_Lightmap = -1;
1185 p->tex_Texture_Deluxemap = -1;
1186 p->tex_Texture_Attenuation = -1;
1187 p->tex_Texture_Cube = -1;
1188 p->tex_Texture_Refraction = -1;
1189 p->tex_Texture_Reflection = -1;
1190 p->tex_Texture_ShadowMap2D = -1;
1191 p->tex_Texture_CubeProjection = -1;
1192 p->tex_Texture_ScreenDepth = -1;
1193 p->tex_Texture_ScreenNormalMap = -1;
1194 p->tex_Texture_ScreenDiffuse = -1;
1195 p->tex_Texture_ScreenSpecular = -1;
1196 p->tex_Texture_ReflectMask = -1;
1197 p->tex_Texture_ReflectCube = -1;
1198 p->tex_Texture_BounceGrid = -1;
1200 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1201 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1202 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1203 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1204 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1205 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1206 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1207 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1209 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1211 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1212 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1213 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1215 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1216 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1217 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1218 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1219 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1220 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1221 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1222 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1223 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1224 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1227 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1228 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1229 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1231 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1234 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1238 Mem_Free(vertexstring);
1240 Mem_Free(geometrystring);
1242 Mem_Free(fragmentstring);
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1247 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248 if (r_glsl_permutation != perm)
1250 r_glsl_permutation = perm;
1251 if (!r_glsl_permutation->program)
1253 if (!r_glsl_permutation->compiled)
1254 R_GLSL_CompilePermutation(perm, mode, permutation);
1255 if (!r_glsl_permutation->program)
1257 // remove features until we find a valid permutation
1259 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1261 // reduce i more quickly whenever it would not remove any bits
1262 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263 if (!(permutation & j))
1266 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267 if (!r_glsl_permutation->compiled)
1268 R_GLSL_CompilePermutation(perm, mode, permutation);
1269 if (r_glsl_permutation->program)
1272 if (i >= SHADERPERMUTATION_COUNT)
1274 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276 qglUseProgram(0);CHECKGLERROR
1277 return; // no bit left to clear, entire mode is broken
1282 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1284 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1300 /// hash lookup data
1301 struct r_hlsl_permutation_s *hashnext;
1303 unsigned int permutation;
1305 /// indicates if we have tried compiling this permutation already
1307 /// NULL if compilation failed
1308 IDirect3DVertexShader9 *vertexshader;
1309 IDirect3DPixelShader9 *pixelshader;
1311 r_hlsl_permutation_t;
1313 typedef enum D3DVSREGISTER_e
1315 D3DVSREGISTER_TexMatrix = 0, // float4x4
1316 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320 D3DVSREGISTER_ModelToLight = 20, // float4x4
1321 D3DVSREGISTER_EyePosition = 24,
1322 D3DVSREGISTER_FogPlane = 25,
1323 D3DVSREGISTER_LightDir = 26,
1324 D3DVSREGISTER_LightPosition = 27,
1328 typedef enum D3DPSREGISTER_e
1330 D3DPSREGISTER_Alpha = 0,
1331 D3DPSREGISTER_BloomBlur_Parameters = 1,
1332 D3DPSREGISTER_ClientTime = 2,
1333 D3DPSREGISTER_Color_Ambient = 3,
1334 D3DPSREGISTER_Color_Diffuse = 4,
1335 D3DPSREGISTER_Color_Specular = 5,
1336 D3DPSREGISTER_Color_Glow = 6,
1337 D3DPSREGISTER_Color_Pants = 7,
1338 D3DPSREGISTER_Color_Shirt = 8,
1339 D3DPSREGISTER_DeferredColor_Ambient = 9,
1340 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341 D3DPSREGISTER_DeferredColor_Specular = 11,
1342 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343 D3DPSREGISTER_DeferredMod_Specular = 13,
1344 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345 D3DPSREGISTER_EyePosition = 15, // unused
1346 D3DPSREGISTER_FogColor = 16,
1347 D3DPSREGISTER_FogHeightFade = 17,
1348 D3DPSREGISTER_FogPlane = 18,
1349 D3DPSREGISTER_FogPlaneViewDist = 19,
1350 D3DPSREGISTER_FogRangeRecip = 20,
1351 D3DPSREGISTER_LightColor = 21,
1352 D3DPSREGISTER_LightDir = 22, // unused
1353 D3DPSREGISTER_LightPosition = 23,
1354 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355 D3DPSREGISTER_PixelSize = 25,
1356 D3DPSREGISTER_ReflectColor = 26,
1357 D3DPSREGISTER_ReflectFactor = 27,
1358 D3DPSREGISTER_ReflectOffset = 28,
1359 D3DPSREGISTER_RefractColor = 29,
1360 D3DPSREGISTER_Saturation = 30,
1361 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363 D3DPSREGISTER_ScreenToDepth = 33,
1364 D3DPSREGISTER_ShadowMap_Parameters = 34,
1365 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366 D3DPSREGISTER_SpecularPower = 36,
1367 D3DPSREGISTER_UserVec1 = 37,
1368 D3DPSREGISTER_UserVec2 = 38,
1369 D3DPSREGISTER_UserVec3 = 39,
1370 D3DPSREGISTER_UserVec4 = 40,
1371 D3DPSREGISTER_ViewTintColor = 41,
1372 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373 D3DPSREGISTER_BloomColorSubtract = 43,
1374 D3DPSREGISTER_ViewToLight = 44, // float4x4
1375 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376 D3DPSREGISTER_NormalmapScrollBlend = 52,
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1390 //unsigned int hashdepth = 0;
1391 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392 r_hlsl_permutation_t *p;
1393 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1395 if (p->mode == mode && p->permutation == permutation)
1397 //if (hashdepth > 10)
1398 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1403 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1405 p->permutation = permutation;
1406 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407 r_hlsl_permutationhash[mode][hashindex] = p;
1408 //if (hashdepth > 10)
1409 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1416 if (!filename || !filename[0])
1418 if (!strcmp(filename, "hlsl/default.hlsl"))
1420 if (!hlslshaderstring)
1422 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423 if (hlslshaderstring)
1424 Con_DPrintf("Loading shaders from file %s...\n", filename);
1426 hlslshaderstring = (char *)builtinhlslshaderstring;
1428 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430 return shaderstring;
1432 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1435 if (printfromdisknotice)
1436 Con_DPrintf("from disk %s... ", filename);
1437 return shaderstring;
1439 return shaderstring;
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1448 DWORD *vsbin = NULL;
1449 DWORD *psbin = NULL;
1450 fs_offset_t vsbinsize;
1451 fs_offset_t psbinsize;
1452 // IDirect3DVertexShader9 *vs = NULL;
1453 // IDirect3DPixelShader9 *ps = NULL;
1454 ID3DXBuffer *vslog = NULL;
1455 ID3DXBuffer *vsbuffer = NULL;
1456 ID3DXConstantTable *vsconstanttable = NULL;
1457 ID3DXBuffer *pslog = NULL;
1458 ID3DXBuffer *psbuffer = NULL;
1459 ID3DXConstantTable *psconstanttable = NULL;
1462 char temp[MAX_INPUTLINE];
1463 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464 qboolean debugshader = gl_paranoid.integer != 0;
1465 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1469 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1472 if ((!vsbin && vertstring) || (!psbin && fragstring))
1474 const char* dllnames_d3dx9 [] =
1498 dllhandle_t d3dx9_dll = NULL;
1499 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502 dllfunction_t d3dx9_dllfuncs[] =
1504 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1505 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1506 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1509 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1511 DWORD shaderflags = 0;
1513 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516 if (vertstring && vertstring[0])
1520 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1526 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1529 vsbinsize = vsbuffer->GetBufferSize();
1530 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532 vsbuffer->Release();
1536 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1541 if (fragstring && fragstring[0])
1545 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1551 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1554 psbinsize = psbuffer->GetBufferSize();
1555 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557 psbuffer->Release();
1561 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1566 Sys_UnloadLibrary(&d3dx9_dll);
1569 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1573 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574 if (FAILED(vsresult))
1575 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577 if (FAILED(psresult))
1578 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1580 // free the shader data
1581 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1588 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589 int vertstring_length = 0;
1590 int geomstring_length = 0;
1591 int fragstring_length = 0;
1593 char *vertexstring, *geometrystring, *fragmentstring;
1594 char *vertstring, *geomstring, *fragstring;
1595 char permutationname[256];
1596 char cachename[256];
1597 int vertstrings_count = 0;
1598 int geomstrings_count = 0;
1599 int fragstrings_count = 0;
1600 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607 p->vertexshader = NULL;
1608 p->pixelshader = NULL;
1610 permutationname[0] = 0;
1612 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1616 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617 strlcat(cachename, "hlsl/", sizeof(cachename));
1619 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620 vertstrings_count = 0;
1621 geomstrings_count = 0;
1622 fragstrings_count = 0;
1623 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1627 // the first pretext is which type of shader to compile as
1628 // (later these will all be bound together as a program object)
1629 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1633 // the second pretext is the mode (for example a light source)
1634 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638 strlcat(cachename, modeinfo->name, sizeof(cachename));
1640 // now add all the permutation pretexts
1641 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1643 if (permutation & (1<<i))
1645 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1653 // keep line numbers correct
1654 vertstrings_list[vertstrings_count++] = "\n";
1655 geomstrings_list[geomstrings_count++] = "\n";
1656 fragstrings_list[fragstrings_count++] = "\n";
1661 R_CompileShader_AddStaticParms(mode, permutation);
1662 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663 vertstrings_count += shaderstaticparms_count;
1664 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665 geomstrings_count += shaderstaticparms_count;
1666 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667 fragstrings_count += shaderstaticparms_count;
1669 // replace spaces in the cachename with _ characters
1670 for (i = 0;cachename[i];i++)
1671 if (cachename[i] == ' ')
1674 // now append the shader text itself
1675 vertstrings_list[vertstrings_count++] = vertexstring;
1676 geomstrings_list[geomstrings_count++] = geometrystring;
1677 fragstrings_list[fragstrings_count++] = fragmentstring;
1679 // if any sources were NULL, clear the respective list
1681 vertstrings_count = 0;
1682 if (!geometrystring)
1683 geomstrings_count = 0;
1684 if (!fragmentstring)
1685 fragstrings_count = 0;
1687 vertstring_length = 0;
1688 for (i = 0;i < vertstrings_count;i++)
1689 vertstring_length += strlen(vertstrings_list[i]);
1690 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1694 geomstring_length = 0;
1695 for (i = 0;i < geomstrings_count;i++)
1696 geomstring_length += strlen(geomstrings_list[i]);
1697 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1701 fragstring_length = 0;
1702 for (i = 0;i < fragstrings_count;i++)
1703 fragstring_length += strlen(fragstrings_list[i]);
1704 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1708 // try to load the cached shader, or generate one
1709 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1711 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1714 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1718 Mem_Free(vertstring);
1720 Mem_Free(geomstring);
1722 Mem_Free(fragstring);
1724 Mem_Free(vertexstring);
1726 Mem_Free(geometrystring);
1728 Mem_Free(fragmentstring);
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1734 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1741 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1742 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1743 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1747 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748 if (r_hlsl_permutation != perm)
1750 r_hlsl_permutation = perm;
1751 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1753 if (!r_hlsl_permutation->compiled)
1754 R_HLSL_CompilePermutation(perm, mode, permutation);
1755 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757 // remove features until we find a valid permutation
1759 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1761 // reduce i more quickly whenever it would not remove any bits
1762 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763 if (!(permutation & j))
1766 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767 if (!r_hlsl_permutation->compiled)
1768 R_HLSL_CompilePermutation(perm, mode, permutation);
1769 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1772 if (i >= SHADERPERMUTATION_COUNT)
1774 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776 return; // no bit left to clear, entire mode is broken
1780 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1783 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1791 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1797 void R_GLSL_Restart_f(void)
1799 unsigned int i, limit;
1800 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801 Mem_Free(glslshaderstring);
1802 glslshaderstring = NULL;
1803 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804 Mem_Free(hlslshaderstring);
1805 hlslshaderstring = NULL;
1806 switch(vid.renderpath)
1808 case RENDERPATH_D3D9:
1811 r_hlsl_permutation_t *p;
1812 r_hlsl_permutation = NULL;
1813 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814 for (i = 0;i < limit;i++)
1816 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1818 if (p->vertexshader)
1819 IDirect3DVertexShader9_Release(p->vertexshader);
1821 IDirect3DPixelShader9_Release(p->pixelshader);
1822 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1825 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1829 case RENDERPATH_D3D10:
1830 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1832 case RENDERPATH_D3D11:
1833 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835 case RENDERPATH_GL20:
1836 case RENDERPATH_GLES2:
1838 r_glsl_permutation_t *p;
1839 r_glsl_permutation = NULL;
1840 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841 for (i = 0;i < limit;i++)
1843 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1845 GL_Backend_FreeProgram(p->program);
1846 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1849 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1852 case RENDERPATH_GL11:
1853 case RENDERPATH_GL13:
1854 case RENDERPATH_GLES1:
1856 case RENDERPATH_SOFT:
1861 void R_GLSL_DumpShader_f(void)
1866 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1869 FS_Print(file, "/* The engine may define the following macros:\n");
1870 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1871 for (i = 0;i < SHADERMODE_COUNT;i++)
1872 FS_Print(file, glslshadermodeinfo[i].pretext);
1873 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1874 FS_Print(file, shaderpermutationinfo[i].pretext);
1875 FS_Print(file, "*/\n");
1876 FS_Print(file, builtinshaderstring);
1878 Con_Printf("glsl/default.glsl written\n");
1881 Con_Printf("failed to write to glsl/default.glsl\n");
1883 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1886 FS_Print(file, "/* The engine may define the following macros:\n");
1887 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1888 for (i = 0;i < SHADERMODE_COUNT;i++)
1889 FS_Print(file, hlslshadermodeinfo[i].pretext);
1890 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1891 FS_Print(file, shaderpermutationinfo[i].pretext);
1892 FS_Print(file, "*/\n");
1893 FS_Print(file, builtinhlslshaderstring);
1895 Con_Printf("hlsl/default.hlsl written\n");
1898 Con_Printf("failed to write to hlsl/default.hlsl\n");
1901 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
1903 unsigned int permutation = 0;
1904 if (r_trippy.integer && !notrippy)
1905 permutation |= SHADERPERMUTATION_TRIPPY;
1906 permutation |= SHADERPERMUTATION_VIEWTINT;
1908 permutation |= SHADERPERMUTATION_DIFFUSE;
1910 permutation |= SHADERPERMUTATION_SPECULAR;
1911 if (texturemode == GL_MODULATE)
1912 permutation |= SHADERPERMUTATION_COLORMAPPING;
1913 else if (texturemode == GL_ADD)
1914 permutation |= SHADERPERMUTATION_GLOW;
1915 else if (texturemode == GL_DECAL)
1916 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1918 texturemode = GL_MODULATE;
1919 if (vid.allowalphatocoverage)
1920 GL_AlphaToCoverage(false);
1921 switch (vid.renderpath)
1923 case RENDERPATH_D3D9:
1925 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1926 R_Mesh_TexBind(GL20TU_FIRST , first );
1927 R_Mesh_TexBind(GL20TU_SECOND, second);
1930 case RENDERPATH_D3D10:
1931 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1933 case RENDERPATH_D3D11:
1934 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1936 case RENDERPATH_GL20:
1937 case RENDERPATH_GLES2:
1938 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1939 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1940 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1942 case RENDERPATH_GL13:
1943 case RENDERPATH_GLES1:
1944 R_Mesh_TexBind(0, first );
1945 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1946 R_Mesh_TexBind(1, second);
1948 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1950 case RENDERPATH_GL11:
1951 R_Mesh_TexBind(0, first );
1953 case RENDERPATH_SOFT:
1954 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1955 R_Mesh_TexBind(GL20TU_FIRST , first );
1956 R_Mesh_TexBind(GL20TU_SECOND, second);
1961 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1963 unsigned int permutation = 0;
1964 if (r_trippy.integer && !notrippy)
1965 permutation |= SHADERPERMUTATION_TRIPPY;
1966 if (vid.allowalphatocoverage)
1967 GL_AlphaToCoverage(false);
1968 switch (vid.renderpath)
1970 case RENDERPATH_D3D9:
1972 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1975 case RENDERPATH_D3D10:
1976 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1978 case RENDERPATH_D3D11:
1979 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1981 case RENDERPATH_GL20:
1982 case RENDERPATH_GLES2:
1983 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1985 case RENDERPATH_GL13:
1986 case RENDERPATH_GLES1:
1987 R_Mesh_TexBind(0, 0);
1988 R_Mesh_TexBind(1, 0);
1990 case RENDERPATH_GL11:
1991 R_Mesh_TexBind(0, 0);
1993 case RENDERPATH_SOFT:
1994 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1999 void R_SetupShader_ShowDepth(qboolean notrippy)
2001 int permutation = 0;
2002 if (r_trippy.integer && !notrippy)
2003 permutation |= SHADERPERMUTATION_TRIPPY;
2004 if (vid.allowalphatocoverage)
2005 GL_AlphaToCoverage(false);
2006 switch (vid.renderpath)
2008 case RENDERPATH_D3D9:
2010 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2013 case RENDERPATH_D3D10:
2014 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2016 case RENDERPATH_D3D11:
2017 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2019 case RENDERPATH_GL20:
2020 case RENDERPATH_GLES2:
2021 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2023 case RENDERPATH_GL13:
2024 case RENDERPATH_GLES1:
2026 case RENDERPATH_GL11:
2028 case RENDERPATH_SOFT:
2029 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2034 extern qboolean r_shadow_usingdeferredprepass;
2035 extern cvar_t r_shadow_deferred_8bitrange;
2036 extern rtexture_t *r_shadow_attenuationgradienttexture;
2037 extern rtexture_t *r_shadow_attenuation2dtexture;
2038 extern rtexture_t *r_shadow_attenuation3dtexture;
2039 extern qboolean r_shadow_usingshadowmap2d;
2040 extern qboolean r_shadow_usingshadowmaportho;
2041 extern float r_shadow_shadowmap_texturescale[2];
2042 extern float r_shadow_shadowmap_parameters[4];
2043 extern qboolean r_shadow_shadowmapvsdct;
2044 extern qboolean r_shadow_shadowmapsampler;
2045 extern int r_shadow_shadowmappcf;
2046 extern rtexture_t *r_shadow_shadowmap2dtexture;
2047 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2048 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2049 extern matrix4x4_t r_shadow_shadowmapmatrix;
2050 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2051 extern int r_shadow_prepass_width;
2052 extern int r_shadow_prepass_height;
2053 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2054 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2055 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2056 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2057 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2059 #define BLENDFUNC_ALLOWS_COLORMOD 1
2060 #define BLENDFUNC_ALLOWS_FOG 2
2061 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2062 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2063 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2064 static int R_BlendFuncFlags(int src, int dst)
2068 // a blendfunc allows colormod if:
2069 // a) it can never keep the destination pixel invariant, or
2070 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2071 // this is to prevent unintended side effects from colormod
2073 // a blendfunc allows fog if:
2074 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2075 // this is to prevent unintended side effects from fog
2077 // these checks are the output of fogeval.pl
2079 r |= BLENDFUNC_ALLOWS_COLORMOD;
2080 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2081 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2082 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2084 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2085 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2086 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2088 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2089 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2090 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2091 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2093 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2094 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2095 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2096 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2097 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2098 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2099 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2100 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2105 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)
2107 // select a permutation of the lighting shader appropriate to this
2108 // combination of texture, entity, light source, and fogging, only use the
2109 // minimum features necessary to avoid wasting rendering time in the
2110 // fragment shader on features that are not being used
2111 unsigned int permutation = 0;
2112 unsigned int mode = 0;
2114 static float dummy_colormod[3] = {1, 1, 1};
2115 float *colormod = rsurface.colormod;
2117 matrix4x4_t tempmatrix;
2118 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2119 if (r_trippy.integer && !notrippy)
2120 permutation |= SHADERPERMUTATION_TRIPPY;
2121 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2122 permutation |= SHADERPERMUTATION_ALPHAKILL;
2123 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2124 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2125 if (rsurfacepass == RSURFPASS_BACKGROUND)
2127 // distorted background
2128 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2130 mode = SHADERMODE_WATER;
2131 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2133 // this is the right thing to do for wateralpha
2134 GL_BlendFunc(GL_ONE, GL_ZERO);
2135 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2139 // this is the right thing to do for entity alpha
2140 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2141 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2144 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2146 mode = SHADERMODE_REFRACTION;
2147 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2148 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2152 mode = SHADERMODE_GENERIC;
2153 permutation |= SHADERPERMUTATION_DIFFUSE;
2154 GL_BlendFunc(GL_ONE, GL_ZERO);
2155 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2157 if (vid.allowalphatocoverage)
2158 GL_AlphaToCoverage(false);
2160 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2162 if (r_glsl_offsetmapping.integer)
2164 switch(rsurface.texture->offsetmapping)
2166 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2167 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2168 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2169 case OFFSETMAPPING_OFF: break;
2172 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2173 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2174 // normalmap (deferred prepass), may use alpha test on diffuse
2175 mode = SHADERMODE_DEFERREDGEOMETRY;
2176 GL_BlendFunc(GL_ONE, GL_ZERO);
2177 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2178 if (vid.allowalphatocoverage)
2179 GL_AlphaToCoverage(false);
2181 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2183 if (r_glsl_offsetmapping.integer)
2185 switch(rsurface.texture->offsetmapping)
2187 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2188 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2189 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2190 case OFFSETMAPPING_OFF: break;
2193 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2194 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2196 mode = SHADERMODE_LIGHTSOURCE;
2197 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2198 permutation |= SHADERPERMUTATION_CUBEFILTER;
2199 if (diffusescale > 0)
2200 permutation |= SHADERPERMUTATION_DIFFUSE;
2201 if (specularscale > 0)
2202 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2203 if (r_refdef.fogenabled)
2204 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2205 if (rsurface.texture->colormapping)
2206 permutation |= SHADERPERMUTATION_COLORMAPPING;
2207 if (r_shadow_usingshadowmap2d)
2209 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2210 if(r_shadow_shadowmapvsdct)
2211 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2213 if (r_shadow_shadowmapsampler)
2214 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2215 if (r_shadow_shadowmappcf > 1)
2216 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2217 else if (r_shadow_shadowmappcf)
2218 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2220 if (rsurface.texture->reflectmasktexture)
2221 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2222 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2223 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2224 if (vid.allowalphatocoverage)
2225 GL_AlphaToCoverage(false);
2227 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2229 if (r_glsl_offsetmapping.integer)
2231 switch(rsurface.texture->offsetmapping)
2233 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2234 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2235 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2236 case OFFSETMAPPING_OFF: break;
2239 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2240 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2241 // unshaded geometry (fullbright or ambient model lighting)
2242 mode = SHADERMODE_FLATCOLOR;
2243 ambientscale = diffusescale = specularscale = 0;
2244 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2245 permutation |= SHADERPERMUTATION_GLOW;
2246 if (r_refdef.fogenabled)
2247 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2248 if (rsurface.texture->colormapping)
2249 permutation |= SHADERPERMUTATION_COLORMAPPING;
2250 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2252 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2253 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2255 if (r_shadow_shadowmapsampler)
2256 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2257 if (r_shadow_shadowmappcf > 1)
2258 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2259 else if (r_shadow_shadowmappcf)
2260 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2262 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2263 permutation |= SHADERPERMUTATION_REFLECTION;
2264 if (rsurface.texture->reflectmasktexture)
2265 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2266 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2267 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2268 // when using alphatocoverage, we don't need alphakill
2269 if (vid.allowalphatocoverage)
2271 if (r_transparent_alphatocoverage.integer)
2273 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2274 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2277 GL_AlphaToCoverage(false);
2280 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2282 if (r_glsl_offsetmapping.integer)
2284 switch(rsurface.texture->offsetmapping)
2286 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2287 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2288 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2289 case OFFSETMAPPING_OFF: break;
2292 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2293 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2294 // directional model lighting
2295 mode = SHADERMODE_LIGHTDIRECTION;
2296 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2297 permutation |= SHADERPERMUTATION_GLOW;
2298 permutation |= SHADERPERMUTATION_DIFFUSE;
2299 if (specularscale > 0)
2300 permutation |= SHADERPERMUTATION_SPECULAR;
2301 if (r_refdef.fogenabled)
2302 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2303 if (rsurface.texture->colormapping)
2304 permutation |= SHADERPERMUTATION_COLORMAPPING;
2305 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2307 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2308 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2310 if (r_shadow_shadowmapsampler)
2311 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2312 if (r_shadow_shadowmappcf > 1)
2313 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2314 else if (r_shadow_shadowmappcf)
2315 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2317 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2318 permutation |= SHADERPERMUTATION_REFLECTION;
2319 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2320 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2321 if (rsurface.texture->reflectmasktexture)
2322 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2323 if (r_shadow_bouncegridtexture)
2325 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2326 if (r_shadow_bouncegriddirectional)
2327 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2329 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2330 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2331 // when using alphatocoverage, we don't need alphakill
2332 if (vid.allowalphatocoverage)
2334 if (r_transparent_alphatocoverage.integer)
2336 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2337 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2340 GL_AlphaToCoverage(false);
2343 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2345 if (r_glsl_offsetmapping.integer)
2347 switch(rsurface.texture->offsetmapping)
2349 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2350 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2351 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2352 case OFFSETMAPPING_OFF: break;
2355 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2356 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2357 // ambient model lighting
2358 mode = SHADERMODE_LIGHTDIRECTION;
2359 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2360 permutation |= SHADERPERMUTATION_GLOW;
2361 if (r_refdef.fogenabled)
2362 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2363 if (rsurface.texture->colormapping)
2364 permutation |= SHADERPERMUTATION_COLORMAPPING;
2365 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2367 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2368 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2370 if (r_shadow_shadowmapsampler)
2371 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2372 if (r_shadow_shadowmappcf > 1)
2373 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2374 else if (r_shadow_shadowmappcf)
2375 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2377 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2378 permutation |= SHADERPERMUTATION_REFLECTION;
2379 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2380 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2381 if (rsurface.texture->reflectmasktexture)
2382 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2383 if (r_shadow_bouncegridtexture)
2385 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2386 if (r_shadow_bouncegriddirectional)
2387 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2389 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2390 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2391 // when using alphatocoverage, we don't need alphakill
2392 if (vid.allowalphatocoverage)
2394 if (r_transparent_alphatocoverage.integer)
2396 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2397 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2400 GL_AlphaToCoverage(false);
2405 if (r_glsl_offsetmapping.integer)
2407 switch(rsurface.texture->offsetmapping)
2409 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2410 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2411 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2412 case OFFSETMAPPING_OFF: break;
2415 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2416 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2418 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2419 permutation |= SHADERPERMUTATION_GLOW;
2420 if (r_refdef.fogenabled)
2421 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2422 if (rsurface.texture->colormapping)
2423 permutation |= SHADERPERMUTATION_COLORMAPPING;
2424 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2426 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2427 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2429 if (r_shadow_shadowmapsampler)
2430 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2431 if (r_shadow_shadowmappcf > 1)
2432 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2433 else if (r_shadow_shadowmappcf)
2434 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2436 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2437 permutation |= SHADERPERMUTATION_REFLECTION;
2438 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2439 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2440 if (rsurface.texture->reflectmasktexture)
2441 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2442 if (FAKELIGHT_ENABLED)
2444 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2445 mode = SHADERMODE_FAKELIGHT;
2446 permutation |= SHADERPERMUTATION_DIFFUSE;
2447 if (specularscale > 0)
2448 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2450 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2452 // deluxemapping (light direction texture)
2453 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2454 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2456 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2457 permutation |= SHADERPERMUTATION_DIFFUSE;
2458 if (specularscale > 0)
2459 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2461 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2463 // fake deluxemapping (uniform light direction in tangentspace)
2464 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2465 permutation |= SHADERPERMUTATION_DIFFUSE;
2466 if (specularscale > 0)
2467 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2469 else if (rsurface.uselightmaptexture)
2471 // ordinary lightmapping (q1bsp, q3bsp)
2472 mode = SHADERMODE_LIGHTMAP;
2476 // ordinary vertex coloring (q3bsp)
2477 mode = SHADERMODE_VERTEXCOLOR;
2479 if (r_shadow_bouncegridtexture)
2481 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2482 if (r_shadow_bouncegriddirectional)
2483 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2485 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2486 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2487 // when using alphatocoverage, we don't need alphakill
2488 if (vid.allowalphatocoverage)
2490 if (r_transparent_alphatocoverage.integer)
2492 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2493 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2496 GL_AlphaToCoverage(false);
2499 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2500 colormod = dummy_colormod;
2501 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2502 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2503 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2504 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2505 switch(vid.renderpath)
2507 case RENDERPATH_D3D9:
2509 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);
2510 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2511 R_SetupShader_SetPermutationHLSL(mode, permutation);
2512 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2513 if (mode == SHADERMODE_LIGHTSOURCE)
2515 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2516 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2520 if (mode == SHADERMODE_LIGHTDIRECTION)
2522 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2525 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2526 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2527 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2528 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2529 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2531 if (mode == SHADERMODE_LIGHTSOURCE)
2533 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2534 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2535 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2536 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2537 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2539 // additive passes are only darkened by fog, not tinted
2540 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2541 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2545 if (mode == SHADERMODE_FLATCOLOR)
2547 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2549 else if (mode == SHADERMODE_LIGHTDIRECTION)
2551 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]);
2552 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2553 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);
2554 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);
2555 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2556 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2557 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2561 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2562 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2563 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);
2564 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);
2565 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2567 // additive passes are only darkened by fog, not tinted
2568 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2569 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2571 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2572 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);
2573 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2574 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2575 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2576 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2577 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2578 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2579 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2580 if (mode == SHADERMODE_WATER)
2581 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2583 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2584 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2585 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2586 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));
2587 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2588 if (rsurface.texture->pantstexture)
2589 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2591 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2592 if (rsurface.texture->shirttexture)
2593 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2595 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2596 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2597 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2598 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2599 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2600 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2601 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2602 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2603 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2604 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2606 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2607 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2609 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2610 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2611 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2612 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2613 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2614 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2615 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2616 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2617 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2618 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2619 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2620 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2621 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2622 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2623 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2624 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2625 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2626 if (rsurfacepass == RSURFPASS_BACKGROUND)
2628 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2629 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2630 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2634 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2636 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2637 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2638 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2639 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2640 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2642 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2643 if (rsurface.rtlight)
2645 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2646 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2651 case RENDERPATH_D3D10:
2652 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2654 case RENDERPATH_D3D11:
2655 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2657 case RENDERPATH_GL20:
2658 case RENDERPATH_GLES2:
2659 if (!vid.useinterleavedarrays)
2661 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);
2662 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2663 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2664 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2665 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2666 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2667 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2668 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2672 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);
2673 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2675 R_SetupShader_SetPermutationGLSL(mode, permutation);
2676 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2677 if (mode == SHADERMODE_LIGHTSOURCE)
2679 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2680 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2681 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2682 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2683 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2684 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);
2686 // additive passes are only darkened by fog, not tinted
2687 if (r_glsl_permutation->loc_FogColor >= 0)
2688 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2689 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2693 if (mode == SHADERMODE_FLATCOLOR)
2695 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2697 else if (mode == SHADERMODE_LIGHTDIRECTION)
2699 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]);
2700 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]);
2701 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);
2702 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);
2703 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);
2704 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]);
2705 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]);
2709 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]);
2710 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]);
2711 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);
2712 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);
2713 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);
2715 // additive passes are only darkened by fog, not tinted
2716 if (r_glsl_permutation->loc_FogColor >= 0)
2718 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2719 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2721 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2723 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);
2724 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]);
2725 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]);
2726 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]);
2727 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]);
2728 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2729 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2730 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2731 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]);
2733 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2734 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2735 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2736 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]);
2737 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]);
2739 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2740 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));
2741 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2742 if (r_glsl_permutation->loc_Color_Pants >= 0)
2744 if (rsurface.texture->pantstexture)
2745 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2747 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2749 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2751 if (rsurface.texture->shirttexture)
2752 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2754 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2756 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]);
2757 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2758 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2759 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2760 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2761 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2762 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2763 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2764 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2766 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]);
2767 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2768 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);}
2769 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2771 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2772 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2773 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2774 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2775 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2776 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2777 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2778 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2779 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2780 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2781 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2782 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2783 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2784 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2785 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);
2786 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2787 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2788 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2789 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2790 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2791 if (rsurfacepass == RSURFPASS_BACKGROUND)
2793 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);
2794 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);
2795 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);
2799 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);
2801 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2802 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2803 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2804 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2805 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2807 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2808 if (rsurface.rtlight)
2810 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2811 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2814 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2817 case RENDERPATH_GL11:
2818 case RENDERPATH_GL13:
2819 case RENDERPATH_GLES1:
2821 case RENDERPATH_SOFT:
2822 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);
2823 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2824 R_SetupShader_SetPermutationSoft(mode, permutation);
2825 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2826 if (mode == SHADERMODE_LIGHTSOURCE)
2828 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2829 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2830 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2831 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2832 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2833 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2835 // additive passes are only darkened by fog, not tinted
2836 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2837 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2841 if (mode == SHADERMODE_FLATCOLOR)
2843 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2845 else if (mode == SHADERMODE_LIGHTDIRECTION)
2847 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]);
2848 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2849 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);
2850 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);
2851 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2852 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]);
2853 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2857 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2858 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2859 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);
2860 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);
2861 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2863 // additive passes are only darkened by fog, not tinted
2864 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2865 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2867 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2868 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);
2869 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2870 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2871 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]);
2872 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]);
2873 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2874 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2875 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2876 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2878 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2879 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2880 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2881 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2882 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]);
2884 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2885 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));
2886 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2887 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2889 if (rsurface.texture->pantstexture)
2890 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2892 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2894 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2896 if (rsurface.texture->shirttexture)
2897 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2899 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2901 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2902 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2903 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2904 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2905 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2906 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2907 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2908 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2909 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2911 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2912 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2914 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2915 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2916 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2917 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2918 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2919 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2920 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2921 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2922 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2923 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2924 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2925 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2926 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2927 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2928 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2929 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2930 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2931 if (rsurfacepass == RSURFPASS_BACKGROUND)
2933 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2934 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2935 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2939 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2941 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2942 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2943 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2944 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2945 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2947 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2948 if (rsurface.rtlight)
2950 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2951 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2958 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2960 // select a permutation of the lighting shader appropriate to this
2961 // combination of texture, entity, light source, and fogging, only use the
2962 // minimum features necessary to avoid wasting rendering time in the
2963 // fragment shader on features that are not being used
2964 unsigned int permutation = 0;
2965 unsigned int mode = 0;
2966 const float *lightcolorbase = rtlight->currentcolor;
2967 float ambientscale = rtlight->ambientscale;
2968 float diffusescale = rtlight->diffusescale;
2969 float specularscale = rtlight->specularscale;
2970 // this is the location of the light in view space
2971 vec3_t viewlightorigin;
2972 // this transforms from view space (camera) to light space (cubemap)
2973 matrix4x4_t viewtolight;
2974 matrix4x4_t lighttoview;
2975 float viewtolight16f[16];
2976 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2978 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2979 if (rtlight->currentcubemap != r_texture_whitecube)
2980 permutation |= SHADERPERMUTATION_CUBEFILTER;
2981 if (diffusescale > 0)
2982 permutation |= SHADERPERMUTATION_DIFFUSE;
2983 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2984 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2985 if (r_shadow_usingshadowmap2d)
2987 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2988 if (r_shadow_shadowmapvsdct)
2989 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2991 if (r_shadow_shadowmapsampler)
2992 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2993 if (r_shadow_shadowmappcf > 1)
2994 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2995 else if (r_shadow_shadowmappcf)
2996 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2998 if (vid.allowalphatocoverage)
2999 GL_AlphaToCoverage(false);
3000 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3001 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3002 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3003 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3004 switch(vid.renderpath)
3006 case RENDERPATH_D3D9:
3008 R_SetupShader_SetPermutationHLSL(mode, permutation);
3009 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3010 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3011 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3012 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3013 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3014 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3015 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3016 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3017 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3018 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3020 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3021 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3022 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3023 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3024 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3025 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3028 case RENDERPATH_D3D10:
3029 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3031 case RENDERPATH_D3D11:
3032 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3034 case RENDERPATH_GL20:
3035 case RENDERPATH_GLES2:
3036 R_SetupShader_SetPermutationGLSL(mode, permutation);
3037 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3038 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3039 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);
3040 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);
3041 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);
3042 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]);
3043 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]);
3044 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));
3045 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]);
3046 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3048 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3049 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3050 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3051 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3052 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3053 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3055 case RENDERPATH_GL11:
3056 case RENDERPATH_GL13:
3057 case RENDERPATH_GLES1:
3059 case RENDERPATH_SOFT:
3060 R_SetupShader_SetPermutationGLSL(mode, permutation);
3061 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3062 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3063 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3064 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3065 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3066 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3067 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]);
3068 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));
3069 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3070 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3072 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3073 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3074 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3075 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3076 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3077 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3082 #define SKINFRAME_HASH 1024
3086 int loadsequence; // incremented each level change
3087 memexpandablearray_t array;
3088 skinframe_t *hash[SKINFRAME_HASH];
3091 r_skinframe_t r_skinframe;
3093 void R_SkinFrame_PrepareForPurge(void)
3095 r_skinframe.loadsequence++;
3096 // wrap it without hitting zero
3097 if (r_skinframe.loadsequence >= 200)
3098 r_skinframe.loadsequence = 1;
3101 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3105 // mark the skinframe as used for the purging code
3106 skinframe->loadsequence = r_skinframe.loadsequence;
3109 void R_SkinFrame_Purge(void)
3113 for (i = 0;i < SKINFRAME_HASH;i++)
3115 for (s = r_skinframe.hash[i];s;s = s->next)
3117 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3119 if (s->merged == s->base)
3121 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3122 R_PurgeTexture(s->stain );s->stain = NULL;
3123 R_PurgeTexture(s->merged);s->merged = NULL;
3124 R_PurgeTexture(s->base );s->base = NULL;
3125 R_PurgeTexture(s->pants );s->pants = NULL;
3126 R_PurgeTexture(s->shirt );s->shirt = NULL;
3127 R_PurgeTexture(s->nmap );s->nmap = NULL;
3128 R_PurgeTexture(s->gloss );s->gloss = NULL;
3129 R_PurgeTexture(s->glow );s->glow = NULL;
3130 R_PurgeTexture(s->fog );s->fog = NULL;
3131 R_PurgeTexture(s->reflect);s->reflect = NULL;
3132 s->loadsequence = 0;
3138 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3140 char basename[MAX_QPATH];
3142 Image_StripImageExtension(name, basename, sizeof(basename));
3144 if( last == NULL ) {
3146 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3147 item = r_skinframe.hash[hashindex];
3152 // linearly search through the hash bucket
3153 for( ; item ; item = item->next ) {
3154 if( !strcmp( item->basename, basename ) ) {
3161 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3165 char basename[MAX_QPATH];
3167 Image_StripImageExtension(name, basename, sizeof(basename));
3169 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3170 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3171 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3175 rtexture_t *dyntexture;
3176 // check whether its a dynamic texture
3177 dyntexture = CL_GetDynTexture( basename );
3178 if (!add && !dyntexture)
3180 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3181 memset(item, 0, sizeof(*item));
3182 strlcpy(item->basename, basename, sizeof(item->basename));
3183 item->base = dyntexture; // either NULL or dyntexture handle
3184 item->textureflags = textureflags;
3185 item->comparewidth = comparewidth;
3186 item->compareheight = compareheight;
3187 item->comparecrc = comparecrc;
3188 item->next = r_skinframe.hash[hashindex];
3189 r_skinframe.hash[hashindex] = item;
3191 else if( item->base == NULL )
3193 rtexture_t *dyntexture;
3194 // check whether its a dynamic texture
3195 // 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]
3196 dyntexture = CL_GetDynTexture( basename );
3197 item->base = dyntexture; // either NULL or dyntexture handle
3200 R_SkinFrame_MarkUsed(item);
3204 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3206 unsigned long long avgcolor[5], wsum; \
3214 for(pix = 0; pix < cnt; ++pix) \
3217 for(comp = 0; comp < 3; ++comp) \
3219 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3222 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3224 for(comp = 0; comp < 3; ++comp) \
3225 avgcolor[comp] += getpixel * w; \
3228 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3229 avgcolor[4] += getpixel; \
3231 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3233 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3234 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3235 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3236 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3239 extern cvar_t gl_picmip;
3240 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3243 unsigned char *pixels;
3244 unsigned char *bumppixels;
3245 unsigned char *basepixels = NULL;
3246 int basepixels_width = 0;
3247 int basepixels_height = 0;
3248 skinframe_t *skinframe;
3249 rtexture_t *ddsbase = NULL;
3250 qboolean ddshasalpha = false;
3251 float ddsavgcolor[4];
3252 char basename[MAX_QPATH];
3253 int miplevel = R_PicmipForFlags(textureflags);
3254 int savemiplevel = miplevel;
3257 if (cls.state == ca_dedicated)
3260 // return an existing skinframe if already loaded
3261 // if loading of the first image fails, don't make a new skinframe as it
3262 // would cause all future lookups of this to be missing
3263 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3264 if (skinframe && skinframe->base)
3267 Image_StripImageExtension(name, basename, sizeof(basename));
3269 // check for DDS texture file first
3270 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3272 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3273 if (basepixels == NULL)
3277 // FIXME handle miplevel
3279 if (developer_loading.integer)
3280 Con_Printf("loading skin \"%s\"\n", name);
3282 // we've got some pixels to store, so really allocate this new texture now
3284 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3285 skinframe->stain = NULL;
3286 skinframe->merged = NULL;
3287 skinframe->base = NULL;
3288 skinframe->pants = NULL;
3289 skinframe->shirt = NULL;
3290 skinframe->nmap = NULL;
3291 skinframe->gloss = NULL;
3292 skinframe->glow = NULL;
3293 skinframe->fog = NULL;
3294 skinframe->reflect = NULL;
3295 skinframe->hasalpha = false;
3299 skinframe->base = ddsbase;
3300 skinframe->hasalpha = ddshasalpha;
3301 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3302 if (r_loadfog && skinframe->hasalpha)
3303 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3304 //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]);
3308 basepixels_width = image_width;
3309 basepixels_height = image_height;
3310 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);
3311 if (textureflags & TEXF_ALPHA)
3313 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3315 if (basepixels[j] < 255)
3317 skinframe->hasalpha = true;
3321 if (r_loadfog && skinframe->hasalpha)
3323 // has transparent pixels
3324 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3325 for (j = 0;j < image_width * image_height * 4;j += 4)
3330 pixels[j+3] = basepixels[j+3];
3332 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);
3336 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3337 //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]);
3338 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3339 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3340 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3341 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3346 mymiplevel = savemiplevel;
3347 if (r_loadnormalmap)
3348 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);
3349 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3351 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3352 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3353 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3354 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3357 // _norm is the name used by tenebrae and has been adopted as standard
3358 if (r_loadnormalmap && skinframe->nmap == NULL)
3360 mymiplevel = savemiplevel;
3361 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3363 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);
3367 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3369 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3370 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3371 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);
3373 Mem_Free(bumppixels);
3375 else if (r_shadow_bumpscale_basetexture.value > 0)
3377 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3378 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3379 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);
3382 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3383 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3386 // _luma is supported only for tenebrae compatibility
3387 // _glow is the preferred name
3388 mymiplevel = savemiplevel;
3389 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))))
3391 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);
3392 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3393 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3394 Mem_Free(pixels);pixels = NULL;
3397 mymiplevel = savemiplevel;
3398 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3400 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);
3401 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3402 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3407 mymiplevel = savemiplevel;
3408 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3410 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);
3411 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3412 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3417 mymiplevel = savemiplevel;
3418 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3420 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);
3421 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3422 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3427 mymiplevel = savemiplevel;
3428 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3430 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);
3431 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3432 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3438 Mem_Free(basepixels);
3443 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3444 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3447 unsigned char *temp1, *temp2;
3448 skinframe_t *skinframe;
3450 if (cls.state == ca_dedicated)
3453 // if already loaded just return it, otherwise make a new skinframe
3454 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3455 if (skinframe && skinframe->base)
3458 skinframe->stain = NULL;
3459 skinframe->merged = NULL;
3460 skinframe->base = NULL;
3461 skinframe->pants = NULL;
3462 skinframe->shirt = NULL;
3463 skinframe->nmap = NULL;
3464 skinframe->gloss = NULL;
3465 skinframe->glow = NULL;
3466 skinframe->fog = NULL;
3467 skinframe->reflect = NULL;
3468 skinframe->hasalpha = false;
3470 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3474 if (developer_loading.integer)
3475 Con_Printf("loading 32bit skin \"%s\"\n", name);
3477 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3479 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3480 temp2 = temp1 + width * height * 4;
3481 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3482 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);
3485 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3486 if (textureflags & TEXF_ALPHA)
3488 for (i = 3;i < width * height * 4;i += 4)
3490 if (skindata[i] < 255)
3492 skinframe->hasalpha = true;
3496 if (r_loadfog && skinframe->hasalpha)
3498 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3499 memcpy(fogpixels, skindata, width * height * 4);
3500 for (i = 0;i < width * height * 4;i += 4)
3501 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3502 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3503 Mem_Free(fogpixels);
3507 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3508 //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]);
3513 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3517 skinframe_t *skinframe;
3519 if (cls.state == ca_dedicated)
3522 // if already loaded just return it, otherwise make a new skinframe
3523 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3524 if (skinframe && skinframe->base)
3527 skinframe->stain = NULL;
3528 skinframe->merged = NULL;
3529 skinframe->base = NULL;
3530 skinframe->pants = NULL;
3531 skinframe->shirt = NULL;
3532 skinframe->nmap = NULL;
3533 skinframe->gloss = NULL;
3534 skinframe->glow = NULL;
3535 skinframe->fog = NULL;
3536 skinframe->reflect = NULL;
3537 skinframe->hasalpha = false;
3539 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3543 if (developer_loading.integer)
3544 Con_Printf("loading quake skin \"%s\"\n", name);
3546 // 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)
3547 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3548 memcpy(skinframe->qpixels, skindata, width*height);
3549 skinframe->qwidth = width;
3550 skinframe->qheight = height;
3553 for (i = 0;i < width * height;i++)
3554 featuresmask |= palette_featureflags[skindata[i]];
3556 skinframe->hasalpha = false;
3557 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3558 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3559 skinframe->qgeneratemerged = true;
3560 skinframe->qgeneratebase = skinframe->qhascolormapping;
3561 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3563 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3564 //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]);
3569 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3573 unsigned char *skindata;
3575 if (!skinframe->qpixels)
3578 if (!skinframe->qhascolormapping)
3579 colormapped = false;
3583 if (!skinframe->qgeneratebase)
3588 if (!skinframe->qgeneratemerged)
3592 width = skinframe->qwidth;
3593 height = skinframe->qheight;
3594 skindata = skinframe->qpixels;
3596 if (skinframe->qgeneratenmap)
3598 unsigned char *temp1, *temp2;
3599 skinframe->qgeneratenmap = false;
3600 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3601 temp2 = temp1 + width * height * 4;
3602 // use either a custom palette or the quake palette
3603 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3604 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3605 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);
3609 if (skinframe->qgenerateglow)
3611 skinframe->qgenerateglow = false;
3612 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
3617 skinframe->qgeneratebase = false;
3618 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);
3619 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);
3620 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);
3624 skinframe->qgeneratemerged = false;
3625 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);
3628 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3630 Mem_Free(skinframe->qpixels);
3631 skinframe->qpixels = NULL;
3635 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)
3638 skinframe_t *skinframe;
3640 if (cls.state == ca_dedicated)
3643 // if already loaded just return it, otherwise make a new skinframe
3644 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3645 if (skinframe && skinframe->base)
3648 skinframe->stain = NULL;
3649 skinframe->merged = NULL;
3650 skinframe->base = NULL;
3651 skinframe->pants = NULL;
3652 skinframe->shirt = NULL;
3653 skinframe->nmap = NULL;
3654 skinframe->gloss = NULL;
3655 skinframe->glow = NULL;
3656 skinframe->fog = NULL;
3657 skinframe->reflect = NULL;
3658 skinframe->hasalpha = false;
3660 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3664 if (developer_loading.integer)
3665 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3667 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3668 if (textureflags & TEXF_ALPHA)
3670 for (i = 0;i < width * height;i++)
3672 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3674 skinframe->hasalpha = true;
3678 if (r_loadfog && skinframe->hasalpha)
3679 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3682 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3683 //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]);
3688 skinframe_t *R_SkinFrame_LoadMissing(void)
3690 skinframe_t *skinframe;
3692 if (cls.state == ca_dedicated)
3695 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3696 skinframe->stain = NULL;
3697 skinframe->merged = NULL;
3698 skinframe->base = NULL;
3699 skinframe->pants = NULL;
3700 skinframe->shirt = NULL;
3701 skinframe->nmap = NULL;
3702 skinframe->gloss = NULL;
3703 skinframe->glow = NULL;
3704 skinframe->fog = NULL;
3705 skinframe->reflect = NULL;
3706 skinframe->hasalpha = false;
3708 skinframe->avgcolor[0] = rand() / RAND_MAX;
3709 skinframe->avgcolor[1] = rand() / RAND_MAX;
3710 skinframe->avgcolor[2] = rand() / RAND_MAX;
3711 skinframe->avgcolor[3] = 1;
3716 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3717 typedef struct suffixinfo_s
3720 qboolean flipx, flipy, flipdiagonal;
3723 static suffixinfo_t suffix[3][6] =
3726 {"px", false, false, false},
3727 {"nx", false, false, false},
3728 {"py", false, false, false},
3729 {"ny", false, false, false},
3730 {"pz", false, false, false},
3731 {"nz", false, false, false}
3734 {"posx", false, false, false},
3735 {"negx", false, false, false},
3736 {"posy", false, false, false},
3737 {"negy", false, false, false},
3738 {"posz", false, false, false},
3739 {"negz", false, false, false}
3742 {"rt", true, false, true},
3743 {"lf", false, true, true},
3744 {"ft", true, true, false},
3745 {"bk", false, false, false},
3746 {"up", true, false, true},
3747 {"dn", true, false, true}
3751 static int componentorder[4] = {0, 1, 2, 3};
3753 rtexture_t *R_LoadCubemap(const char *basename)
3755 int i, j, cubemapsize;
3756 unsigned char *cubemappixels, *image_buffer;
3757 rtexture_t *cubemaptexture;
3759 // must start 0 so the first loadimagepixels has no requested width/height
3761 cubemappixels = NULL;
3762 cubemaptexture = NULL;
3763 // keep trying different suffix groups (posx, px, rt) until one loads
3764 for (j = 0;j < 3 && !cubemappixels;j++)
3766 // load the 6 images in the suffix group
3767 for (i = 0;i < 6;i++)
3769 // generate an image name based on the base and and suffix
3770 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3772 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3774 // an image loaded, make sure width and height are equal
3775 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3777 // if this is the first image to load successfully, allocate the cubemap memory
3778 if (!cubemappixels && image_width >= 1)
3780 cubemapsize = image_width;
3781 // note this clears to black, so unavailable sides are black
3782 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3784 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3786 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);
3789 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3791 Mem_Free(image_buffer);
3795 // if a cubemap loaded, upload it
3798 if (developer_loading.integer)
3799 Con_Printf("loading cubemap \"%s\"\n", basename);
3801 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);
3802 Mem_Free(cubemappixels);
3806 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3807 if (developer_loading.integer)
3809 Con_Printf("(tried tried images ");
3810 for (j = 0;j < 3;j++)
3811 for (i = 0;i < 6;i++)
3812 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3813 Con_Print(" and was unable to find any of them).\n");
3816 return cubemaptexture;
3819 rtexture_t *R_GetCubemap(const char *basename)
3822 for (i = 0;i < r_texture_numcubemaps;i++)
3823 if (r_texture_cubemaps[i] != NULL)
3824 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3825 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3826 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3827 return r_texture_whitecube;
3828 r_texture_numcubemaps++;
3829 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3830 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3831 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3832 return r_texture_cubemaps[i]->texture;
3835 void R_FreeCubemap(const char *basename)
3839 for (i = 0;i < r_texture_numcubemaps;i++)
3841 if (r_texture_cubemaps[i] != NULL)
3843 if (r_texture_cubemaps[i]->texture)
3845 if (developer_loading.integer)
3846 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3847 R_FreeTexture(r_texture_cubemaps[i]->texture);
3848 Mem_Free(r_texture_cubemaps[i]);
3849 r_texture_cubemaps[i] = NULL;
3855 void R_FreeCubemaps(void)
3858 for (i = 0;i < r_texture_numcubemaps;i++)
3860 if (developer_loading.integer)
3861 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3862 if (r_texture_cubemaps[i] != NULL)
3864 if (r_texture_cubemaps[i]->texture)
3865 R_FreeTexture(r_texture_cubemaps[i]->texture);
3866 Mem_Free(r_texture_cubemaps[i]);
3869 r_texture_numcubemaps = 0;
3872 void R_Main_FreeViewCache(void)
3874 if (r_refdef.viewcache.entityvisible)
3875 Mem_Free(r_refdef.viewcache.entityvisible);
3876 if (r_refdef.viewcache.world_pvsbits)
3877 Mem_Free(r_refdef.viewcache.world_pvsbits);
3878 if (r_refdef.viewcache.world_leafvisible)
3879 Mem_Free(r_refdef.viewcache.world_leafvisible);
3880 if (r_refdef.viewcache.world_surfacevisible)
3881 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3882 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3885 void R_Main_ResizeViewCache(void)
3887 int numentities = r_refdef.scene.numentities;
3888 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3889 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3890 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3891 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3892 if (r_refdef.viewcache.maxentities < numentities)
3894 r_refdef.viewcache.maxentities = numentities;
3895 if (r_refdef.viewcache.entityvisible)
3896 Mem_Free(r_refdef.viewcache.entityvisible);
3897 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3899 if (r_refdef.viewcache.world_numclusters != numclusters)
3901 r_refdef.viewcache.world_numclusters = numclusters;
3902 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3903 if (r_refdef.viewcache.world_pvsbits)
3904 Mem_Free(r_refdef.viewcache.world_pvsbits);
3905 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3907 if (r_refdef.viewcache.world_numleafs != numleafs)
3909 r_refdef.viewcache.world_numleafs = numleafs;
3910 if (r_refdef.viewcache.world_leafvisible)
3911 Mem_Free(r_refdef.viewcache.world_leafvisible);
3912 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3914 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3916 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3917 if (r_refdef.viewcache.world_surfacevisible)
3918 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3919 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3923 extern rtexture_t *loadingscreentexture;
3924 void gl_main_start(void)
3926 loadingscreentexture = NULL;
3927 r_texture_blanknormalmap = NULL;
3928 r_texture_white = NULL;
3929 r_texture_grey128 = NULL;
3930 r_texture_black = NULL;
3931 r_texture_whitecube = NULL;
3932 r_texture_normalizationcube = NULL;
3933 r_texture_fogattenuation = NULL;
3934 r_texture_fogheighttexture = NULL;
3935 r_texture_gammaramps = NULL;
3936 r_texture_numcubemaps = 0;
3938 r_loaddds = r_texture_dds_load.integer != 0;
3939 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3941 switch(vid.renderpath)
3943 case RENDERPATH_GL20:
3944 case RENDERPATH_D3D9:
3945 case RENDERPATH_D3D10:
3946 case RENDERPATH_D3D11:
3947 case RENDERPATH_SOFT:
3948 case RENDERPATH_GLES2:
3949 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3950 Cvar_SetValueQuick(&gl_combine, 1);
3951 Cvar_SetValueQuick(&r_glsl, 1);
3952 r_loadnormalmap = true;
3956 case RENDERPATH_GL13:
3957 case RENDERPATH_GLES1:
3958 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3959 Cvar_SetValueQuick(&gl_combine, 1);
3960 Cvar_SetValueQuick(&r_glsl, 0);
3961 r_loadnormalmap = false;
3962 r_loadgloss = false;
3965 case RENDERPATH_GL11:
3966 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3967 Cvar_SetValueQuick(&gl_combine, 0);
3968 Cvar_SetValueQuick(&r_glsl, 0);
3969 r_loadnormalmap = false;
3970 r_loadgloss = false;
3976 R_FrameData_Reset();
3980 memset(r_queries, 0, sizeof(r_queries));
3982 r_qwskincache = NULL;
3983 r_qwskincache_size = 0;
3985 // due to caching of texture_t references, the collision cache must be reset
3986 Collision_Cache_Reset(true);
3988 // set up r_skinframe loading system for textures
3989 memset(&r_skinframe, 0, sizeof(r_skinframe));
3990 r_skinframe.loadsequence = 1;
3991 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3993 r_main_texturepool = R_AllocTexturePool();
3994 R_BuildBlankTextures();
3996 if (vid.support.arb_texture_cube_map)
3999 R_BuildNormalizationCube();
4001 r_texture_fogattenuation = NULL;
4002 r_texture_fogheighttexture = NULL;
4003 r_texture_gammaramps = NULL;
4004 //r_texture_fogintensity = NULL;
4005 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4006 memset(&r_waterstate, 0, sizeof(r_waterstate));
4007 r_glsl_permutation = NULL;
4008 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4009 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4010 glslshaderstring = NULL;
4012 r_hlsl_permutation = NULL;
4013 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4014 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4016 hlslshaderstring = NULL;
4017 memset(&r_svbsp, 0, sizeof (r_svbsp));
4019 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4020 r_texture_numcubemaps = 0;
4022 r_refdef.fogmasktable_density = 0;
4025 void gl_main_shutdown(void)
4028 R_FrameData_Reset();
4030 R_Main_FreeViewCache();
4032 switch(vid.renderpath)
4034 case RENDERPATH_GL11:
4035 case RENDERPATH_GL13:
4036 case RENDERPATH_GL20:
4037 case RENDERPATH_GLES1:
4038 case RENDERPATH_GLES2:
4040 qglDeleteQueriesARB(r_maxqueries, r_queries);
4042 case RENDERPATH_D3D9:
4043 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4045 case RENDERPATH_D3D10:
4046 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4048 case RENDERPATH_D3D11:
4049 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4051 case RENDERPATH_SOFT:
4057 memset(r_queries, 0, sizeof(r_queries));
4059 r_qwskincache = NULL;
4060 r_qwskincache_size = 0;
4062 // clear out the r_skinframe state
4063 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4064 memset(&r_skinframe, 0, sizeof(r_skinframe));
4067 Mem_Free(r_svbsp.nodes);
4068 memset(&r_svbsp, 0, sizeof (r_svbsp));
4069 R_FreeTexturePool(&r_main_texturepool);
4070 loadingscreentexture = NULL;
4071 r_texture_blanknormalmap = NULL;
4072 r_texture_white = NULL;
4073 r_texture_grey128 = NULL;
4074 r_texture_black = NULL;
4075 r_texture_whitecube = NULL;
4076 r_texture_normalizationcube = NULL;
4077 r_texture_fogattenuation = NULL;
4078 r_texture_fogheighttexture = NULL;
4079 r_texture_gammaramps = NULL;
4080 r_texture_numcubemaps = 0;
4081 //r_texture_fogintensity = NULL;
4082 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4083 memset(&r_waterstate, 0, sizeof(r_waterstate));
4086 r_glsl_permutation = NULL;
4087 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4088 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4089 glslshaderstring = NULL;
4091 r_hlsl_permutation = NULL;
4092 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4093 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4095 hlslshaderstring = NULL;
4098 extern void CL_ParseEntityLump(char *entitystring);
4099 void gl_main_newmap(void)
4101 // FIXME: move this code to client
4102 char *entities, entname[MAX_QPATH];
4104 Mem_Free(r_qwskincache);
4105 r_qwskincache = NULL;
4106 r_qwskincache_size = 0;
4109 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4110 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4112 CL_ParseEntityLump(entities);
4116 if (cl.worldmodel->brush.entities)
4117 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4119 R_Main_FreeViewCache();
4121 R_FrameData_Reset();
4124 void GL_Main_Init(void)
4126 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4128 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4129 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4130 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4131 if (gamemode == GAME_NEHAHRA)
4133 Cvar_RegisterVariable (&gl_fogenable);
4134 Cvar_RegisterVariable (&gl_fogdensity);
4135 Cvar_RegisterVariable (&gl_fogred);
4136 Cvar_RegisterVariable (&gl_foggreen);
4137 Cvar_RegisterVariable (&gl_fogblue);
4138 Cvar_RegisterVariable (&gl_fogstart);
4139 Cvar_RegisterVariable (&gl_fogend);
4140 Cvar_RegisterVariable (&gl_skyclip);
4142 Cvar_RegisterVariable(&r_motionblur);
4143 Cvar_RegisterVariable(&r_damageblur);
4144 Cvar_RegisterVariable(&r_motionblur_averaging);
4145 Cvar_RegisterVariable(&r_motionblur_randomize);
4146 Cvar_RegisterVariable(&r_motionblur_minblur);
4147 Cvar_RegisterVariable(&r_motionblur_maxblur);
4148 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4149 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4150 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4151 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4152 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4153 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4154 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4155 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4156 Cvar_RegisterVariable(&r_equalize_entities_by);
4157 Cvar_RegisterVariable(&r_equalize_entities_to);
4158 Cvar_RegisterVariable(&r_depthfirst);
4159 Cvar_RegisterVariable(&r_useinfinitefarclip);
4160 Cvar_RegisterVariable(&r_farclip_base);
4161 Cvar_RegisterVariable(&r_farclip_world);
4162 Cvar_RegisterVariable(&r_nearclip);
4163 Cvar_RegisterVariable(&r_deformvertexes);
4164 Cvar_RegisterVariable(&r_transparent);
4165 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4166 Cvar_RegisterVariable(&r_showoverdraw);
4167 Cvar_RegisterVariable(&r_showbboxes);
4168 Cvar_RegisterVariable(&r_showsurfaces);
4169 Cvar_RegisterVariable(&r_showtris);
4170 Cvar_RegisterVariable(&r_shownormals);
4171 Cvar_RegisterVariable(&r_showlighting);
4172 Cvar_RegisterVariable(&r_showshadowvolumes);
4173 Cvar_RegisterVariable(&r_showcollisionbrushes);
4174 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4175 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4176 Cvar_RegisterVariable(&r_showdisabledepthtest);
4177 Cvar_RegisterVariable(&r_drawportals);
4178 Cvar_RegisterVariable(&r_drawentities);
4179 Cvar_RegisterVariable(&r_draw2d);
4180 Cvar_RegisterVariable(&r_drawworld);
4181 Cvar_RegisterVariable(&r_cullentities_trace);
4182 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4183 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4184 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4185 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4186 Cvar_RegisterVariable(&r_drawviewmodel);
4187 Cvar_RegisterVariable(&r_drawexteriormodel);
4188 Cvar_RegisterVariable(&r_speeds);
4189 Cvar_RegisterVariable(&r_fullbrights);
4190 Cvar_RegisterVariable(&r_wateralpha);
4191 Cvar_RegisterVariable(&r_dynamic);
4192 Cvar_RegisterVariable(&r_fakelight);
4193 Cvar_RegisterVariable(&r_fakelight_intensity);
4194 Cvar_RegisterVariable(&r_fullbright);
4195 Cvar_RegisterVariable(&r_shadows);
4196 Cvar_RegisterVariable(&r_shadows_darken);
4197 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4198 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4199 Cvar_RegisterVariable(&r_shadows_throwdistance);
4200 Cvar_RegisterVariable(&r_shadows_throwdirection);
4201 Cvar_RegisterVariable(&r_shadows_focus);
4202 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4203 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4204 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4205 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4206 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4207 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4208 Cvar_RegisterVariable(&r_fog_exp2);
4209 Cvar_RegisterVariable(&r_fog_clear);
4210 Cvar_RegisterVariable(&r_drawfog);
4211 Cvar_RegisterVariable(&r_transparentdepthmasking);
4212 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4213 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4214 Cvar_RegisterVariable(&r_texture_dds_load);
4215 Cvar_RegisterVariable(&r_texture_dds_save);
4216 Cvar_RegisterVariable(&r_textureunits);
4217 Cvar_RegisterVariable(&gl_combine);
4218 Cvar_RegisterVariable(&r_viewfbo);
4219 Cvar_RegisterVariable(&r_viewscale);
4220 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4221 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4222 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4223 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4224 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4225 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4226 Cvar_RegisterVariable(&r_glsl);
4227 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4228 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4229 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4230 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4231 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4232 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4233 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4234 Cvar_RegisterVariable(&r_glsl_postprocess);
4235 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4236 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4237 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4238 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4239 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4240 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4241 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4242 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4244 Cvar_RegisterVariable(&r_water);
4245 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4246 Cvar_RegisterVariable(&r_water_clippingplanebias);
4247 Cvar_RegisterVariable(&r_water_refractdistort);
4248 Cvar_RegisterVariable(&r_water_reflectdistort);
4249 Cvar_RegisterVariable(&r_water_scissormode);
4250 Cvar_RegisterVariable(&r_water_lowquality);
4252 Cvar_RegisterVariable(&r_lerpsprites);
4253 Cvar_RegisterVariable(&r_lerpmodels);
4254 Cvar_RegisterVariable(&r_lerplightstyles);
4255 Cvar_RegisterVariable(&r_waterscroll);
4256 Cvar_RegisterVariable(&r_bloom);
4257 Cvar_RegisterVariable(&r_bloom_colorscale);
4258 Cvar_RegisterVariable(&r_bloom_brighten);
4259 Cvar_RegisterVariable(&r_bloom_blur);
4260 Cvar_RegisterVariable(&r_bloom_resolution);
4261 Cvar_RegisterVariable(&r_bloom_colorexponent);
4262 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4263 Cvar_RegisterVariable(&r_hdr);
4264 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4265 Cvar_RegisterVariable(&r_hdr_glowintensity);
4266 Cvar_RegisterVariable(&r_hdr_range);
4267 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4268 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4269 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4270 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4271 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4272 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4273 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4274 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4275 Cvar_RegisterVariable(&developer_texturelogging);
4276 Cvar_RegisterVariable(&gl_lightmaps);
4277 Cvar_RegisterVariable(&r_test);
4278 Cvar_RegisterVariable(&r_glsl_saturation);
4279 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4280 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4281 Cvar_RegisterVariable(&r_framedatasize);
4282 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4283 Cvar_SetValue("r_fullbrights", 0);
4284 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4287 extern void R_Textures_Init(void);
4288 extern void GL_Draw_Init(void);
4289 extern void GL_Main_Init(void);
4290 extern void R_Shadow_Init(void);
4291 extern void R_Sky_Init(void);
4292 extern void GL_Surf_Init(void);
4293 extern void R_Particles_Init(void);
4294 extern void R_Explosion_Init(void);
4295 extern void gl_backend_init(void);
4296 extern void Sbar_Init(void);
4297 extern void R_LightningBeams_Init(void);
4298 extern void Mod_RenderInit(void);
4299 extern void Font_Init(void);
4301 void Render_Init(void)
4314 R_LightningBeams_Init();
4323 extern char *ENGINE_EXTENSIONS;
4326 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4327 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4328 gl_version = (const char *)qglGetString(GL_VERSION);
4329 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4333 if (!gl_platformextensions)
4334 gl_platformextensions = "";
4336 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4337 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4338 Con_Printf("GL_VERSION: %s\n", gl_version);
4339 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4340 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4342 VID_CheckExtensions();
4344 // LordHavoc: report supported extensions
4345 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4347 // clear to black (loading plaque will be seen over this)
4348 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4351 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4355 if (r_trippy.integer)
4357 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4359 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4362 p = r_refdef.view.frustum + i;
4367 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4371 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4375 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4379 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4383 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4387 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4391 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4395 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4403 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4407 if (r_trippy.integer)
4409 for (i = 0;i < numplanes;i++)
4416 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4420 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4424 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4428 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4432 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4436 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4440 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4444 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4452 //==================================================================================
4454 // LordHavoc: this stores temporary data used within the same frame
4456 typedef struct r_framedata_mem_s
4458 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4459 size_t size; // how much usable space
4460 size_t current; // how much space in use
4461 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4462 size_t wantedsize; // how much space was allocated
4463 unsigned char *data; // start of real data (16byte aligned)
4467 static r_framedata_mem_t *r_framedata_mem;
4469 void R_FrameData_Reset(void)
4471 while (r_framedata_mem)
4473 r_framedata_mem_t *next = r_framedata_mem->purge;
4474 Mem_Free(r_framedata_mem);
4475 r_framedata_mem = next;
4479 void R_FrameData_Resize(void)
4482 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4483 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4484 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4486 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4487 newmem->wantedsize = wantedsize;
4488 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4489 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4490 newmem->current = 0;
4492 newmem->purge = r_framedata_mem;
4493 r_framedata_mem = newmem;
4497 void R_FrameData_NewFrame(void)
4499 R_FrameData_Resize();
4500 if (!r_framedata_mem)
4502 // if we ran out of space on the last frame, free the old memory now
4503 while (r_framedata_mem->purge)
4505 // repeatedly remove the second item in the list, leaving only head
4506 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4507 Mem_Free(r_framedata_mem->purge);
4508 r_framedata_mem->purge = next;
4510 // reset the current mem pointer
4511 r_framedata_mem->current = 0;
4512 r_framedata_mem->mark = 0;
4515 void *R_FrameData_Alloc(size_t size)
4519 // align to 16 byte boundary - the data pointer is already aligned, so we
4520 // only need to ensure the size of every allocation is also aligned
4521 size = (size + 15) & ~15;
4523 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4525 // emergency - we ran out of space, allocate more memory
4526 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4527 R_FrameData_Resize();
4530 data = r_framedata_mem->data + r_framedata_mem->current;
4531 r_framedata_mem->current += size;
4533 // count the usage for stats
4534 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4535 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4537 return (void *)data;
4540 void *R_FrameData_Store(size_t size, void *data)
4542 void *d = R_FrameData_Alloc(size);
4544 memcpy(d, data, size);
4548 void R_FrameData_SetMark(void)
4550 if (!r_framedata_mem)
4552 r_framedata_mem->mark = r_framedata_mem->current;
4555 void R_FrameData_ReturnToMark(void)
4557 if (!r_framedata_mem)
4559 r_framedata_mem->current = r_framedata_mem->mark;
4562 //==================================================================================
4564 // LordHavoc: animcache originally written by Echon, rewritten since then
4567 * Animation cache prevents re-generating mesh data for an animated model
4568 * multiple times in one frame for lighting, shadowing, reflections, etc.
4571 void R_AnimCache_Free(void)
4575 void R_AnimCache_ClearCache(void)
4578 entity_render_t *ent;
4580 for (i = 0;i < r_refdef.scene.numentities;i++)
4582 ent = r_refdef.scene.entities[i];
4583 ent->animcache_vertex3f = NULL;
4584 ent->animcache_normal3f = NULL;
4585 ent->animcache_svector3f = NULL;
4586 ent->animcache_tvector3f = NULL;
4587 ent->animcache_vertexmesh = NULL;
4588 ent->animcache_vertex3fbuffer = NULL;
4589 ent->animcache_vertexmeshbuffer = NULL;
4593 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4597 // check if we need the meshbuffers
4598 if (!vid.useinterleavedarrays)
4601 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4602 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4603 // TODO: upload vertex3f buffer?
4604 if (ent->animcache_vertexmesh)
4606 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4607 for (i = 0;i < numvertices;i++)
4608 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4609 if (ent->animcache_svector3f)
4610 for (i = 0;i < numvertices;i++)
4611 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4612 if (ent->animcache_tvector3f)
4613 for (i = 0;i < numvertices;i++)
4614 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4615 if (ent->animcache_normal3f)
4616 for (i = 0;i < numvertices;i++)
4617 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4618 // TODO: upload vertexmeshbuffer?
4622 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4624 dp_model_t *model = ent->model;
4626 // see if it's already cached this frame
4627 if (ent->animcache_vertex3f)
4629 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4630 if (wantnormals || wanttangents)
4632 if (ent->animcache_normal3f)
4633 wantnormals = false;
4634 if (ent->animcache_svector3f)
4635 wanttangents = false;
4636 if (wantnormals || wanttangents)
4638 numvertices = model->surfmesh.num_vertices;
4640 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4643 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4644 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4646 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4647 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4653 // see if this ent is worth caching
4654 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4656 // get some memory for this entity and generate mesh data
4657 numvertices = model->surfmesh.num_vertices;
4658 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4660 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4663 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4664 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4666 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4667 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4672 void R_AnimCache_CacheVisibleEntities(void)
4675 qboolean wantnormals = true;
4676 qboolean wanttangents = !r_showsurfaces.integer;
4678 switch(vid.renderpath)
4680 case RENDERPATH_GL20:
4681 case RENDERPATH_D3D9:
4682 case RENDERPATH_D3D10:
4683 case RENDERPATH_D3D11:
4684 case RENDERPATH_GLES2:
4686 case RENDERPATH_GL11:
4687 case RENDERPATH_GL13:
4688 case RENDERPATH_GLES1:
4689 wanttangents = false;
4691 case RENDERPATH_SOFT:
4695 if (r_shownormals.integer)
4696 wanttangents = wantnormals = true;
4698 // TODO: thread this
4699 // NOTE: R_PrepareRTLights() also caches entities
4701 for (i = 0;i < r_refdef.scene.numentities;i++)
4702 if (r_refdef.viewcache.entityvisible[i])
4703 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4706 //==================================================================================
4708 extern cvar_t r_overheadsprites_pushback;
4710 static void R_View_UpdateEntityLighting (void)
4713 entity_render_t *ent;
4714 vec3_t tempdiffusenormal, avg;
4715 vec_t f, fa, fd, fdd;
4716 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4718 for (i = 0;i < r_refdef.scene.numentities;i++)
4720 ent = r_refdef.scene.entities[i];
4722 // skip unseen models
4723 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4727 if (ent->model && ent->model->brush.num_leafs)
4729 // TODO: use modellight for r_ambient settings on world?
4730 VectorSet(ent->modellight_ambient, 0, 0, 0);
4731 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4732 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4736 // fetch the lighting from the worldmodel data
4737 VectorClear(ent->modellight_ambient);
4738 VectorClear(ent->modellight_diffuse);
4739 VectorClear(tempdiffusenormal);
4740 if (ent->flags & RENDER_LIGHT)
4743 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4745 // complete lightning for lit sprites
4746 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4747 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4749 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4750 org[2] = org[2] + r_overheadsprites_pushback.value;
4751 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4754 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4756 if(ent->flags & RENDER_EQUALIZE)
4758 // first fix up ambient lighting...
4759 if(r_equalize_entities_minambient.value > 0)
4761 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4764 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4765 if(fa < r_equalize_entities_minambient.value * fd)
4768 // fa'/fd' = minambient
4769 // fa'+0.25*fd' = fa+0.25*fd
4771 // fa' = fd' * minambient
4772 // fd'*(0.25+minambient) = fa+0.25*fd
4774 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4775 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4777 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4778 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
4779 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4780 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4785 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4787 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4788 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4792 // adjust brightness and saturation to target
4793 avg[0] = avg[1] = avg[2] = fa / f;
4794 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4795 avg[0] = avg[1] = avg[2] = fd / f;
4796 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4802 VectorSet(ent->modellight_ambient, 1, 1, 1);
4804 // move the light direction into modelspace coordinates for lighting code
4805 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4806 if(VectorLength2(ent->modellight_lightdir) == 0)
4807 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4808 VectorNormalize(ent->modellight_lightdir);
4812 #define MAX_LINEOFSIGHTTRACES 64
4814 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4817 vec3_t boxmins, boxmaxs;
4820 dp_model_t *model = r_refdef.scene.worldmodel;
4822 if (!model || !model->brush.TraceLineOfSight)
4825 // expand the box a little
4826 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4827 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4828 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4829 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4830 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4831 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4833 // return true if eye is inside enlarged box
4834 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4838 VectorCopy(eye, start);
4839 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4840 if (model->brush.TraceLineOfSight(model, start, end))
4843 // try various random positions
4844 for (i = 0;i < numsamples;i++)
4846 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4847 if (model->brush.TraceLineOfSight(model, start, end))
4855 static void R_View_UpdateEntityVisible (void)
4860 entity_render_t *ent;
4862 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4863 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4864 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4865 : RENDER_EXTERIORMODEL;
4866 if (!r_drawviewmodel.integer)
4867 renderimask |= RENDER_VIEWMODEL;
4868 if (!r_drawexteriormodel.integer)
4869 renderimask |= RENDER_EXTERIORMODEL;
4870 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4872 // worldmodel can check visibility
4873 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4874 for (i = 0;i < r_refdef.scene.numentities;i++)
4876 ent = r_refdef.scene.entities[i];
4877 if (!(ent->flags & renderimask))
4878 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)))
4879 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))
4880 r_refdef.viewcache.entityvisible[i] = true;
4885 // no worldmodel or it can't check visibility
4886 for (i = 0;i < r_refdef.scene.numentities;i++)
4888 ent = r_refdef.scene.entities[i];
4889 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));
4892 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4893 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4895 for (i = 0;i < r_refdef.scene.numentities;i++)
4897 if (!r_refdef.viewcache.entityvisible[i])
4899 ent = r_refdef.scene.entities[i];
4900 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4902 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4904 continue; // temp entities do pvs only
4905 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4906 ent->last_trace_visibility = realtime;
4907 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4908 r_refdef.viewcache.entityvisible[i] = 0;
4914 /// only used if skyrendermasked, and normally returns false
4915 int R_DrawBrushModelsSky (void)
4918 entity_render_t *ent;
4921 for (i = 0;i < r_refdef.scene.numentities;i++)
4923 if (!r_refdef.viewcache.entityvisible[i])
4925 ent = r_refdef.scene.entities[i];
4926 if (!ent->model || !ent->model->DrawSky)
4928 ent->model->DrawSky(ent);
4934 static void R_DrawNoModel(entity_render_t *ent);
4935 static void R_DrawModels(void)
4938 entity_render_t *ent;
4940 for (i = 0;i < r_refdef.scene.numentities;i++)
4942 if (!r_refdef.viewcache.entityvisible[i])
4944 ent = r_refdef.scene.entities[i];
4945 r_refdef.stats.entities++;
4947 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4950 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4951 Con_Printf("R_DrawModels\n");
4952 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]);
4953 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);
4954 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);
4957 if (ent->model && ent->model->Draw != NULL)
4958 ent->model->Draw(ent);
4964 static void R_DrawModelsDepth(void)
4967 entity_render_t *ent;
4969 for (i = 0;i < r_refdef.scene.numentities;i++)
4971 if (!r_refdef.viewcache.entityvisible[i])
4973 ent = r_refdef.scene.entities[i];
4974 if (ent->model && ent->model->DrawDepth != NULL)
4975 ent->model->DrawDepth(ent);
4979 static void R_DrawModelsDebug(void)
4982 entity_render_t *ent;
4984 for (i = 0;i < r_refdef.scene.numentities;i++)
4986 if (!r_refdef.viewcache.entityvisible[i])
4988 ent = r_refdef.scene.entities[i];
4989 if (ent->model && ent->model->DrawDebug != NULL)
4990 ent->model->DrawDebug(ent);
4994 static void R_DrawModelsAddWaterPlanes(void)
4997 entity_render_t *ent;
4999 for (i = 0;i < r_refdef.scene.numentities;i++)
5001 if (!r_refdef.viewcache.entityvisible[i])
5003 ent = r_refdef.scene.entities[i];
5004 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5005 ent->model->DrawAddWaterPlanes(ent);
5009 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5011 if (r_hdr_irisadaptation.integer)
5015 vec3_t diffusenormal;
5019 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5020 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5021 brightness = max(0.0000001f, brightness);
5022 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5023 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5024 current = r_hdr_irisadaptation_value.value;
5026 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5027 else if (current > goal)
5028 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5029 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5030 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5032 else if (r_hdr_irisadaptation_value.value != 1.0f)
5033 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5036 static void R_View_SetFrustum(const int *scissor)
5039 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5040 vec3_t forward, left, up, origin, v;
5044 // flipped x coordinates (because x points left here)
5045 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5046 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5048 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5049 switch(vid.renderpath)
5051 case RENDERPATH_D3D9:
5052 case RENDERPATH_D3D10:
5053 case RENDERPATH_D3D11:
5054 // non-flipped y coordinates
5055 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5056 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5058 case RENDERPATH_SOFT:
5059 case RENDERPATH_GL11:
5060 case RENDERPATH_GL13:
5061 case RENDERPATH_GL20:
5062 case RENDERPATH_GLES1:
5063 case RENDERPATH_GLES2:
5064 // non-flipped y coordinates
5065 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5066 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5071 // we can't trust r_refdef.view.forward and friends in reflected scenes
5072 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5075 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5076 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5077 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5078 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5079 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5080 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5081 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5082 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5083 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5084 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5085 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5086 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5090 zNear = r_refdef.nearclip;
5091 nudge = 1.0 - 1.0 / (1<<23);
5092 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5093 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5094 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5095 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5096 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5097 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5098 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5099 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5105 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5106 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5107 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5108 r_refdef.view.frustum[0].dist = m[15] - m[12];
5110 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5111 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5112 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5113 r_refdef.view.frustum[1].dist = m[15] + m[12];
5115 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5116 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5117 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5118 r_refdef.view.frustum[2].dist = m[15] - m[13];
5120 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5121 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5122 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5123 r_refdef.view.frustum[3].dist = m[15] + m[13];
5125 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5126 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5127 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5128 r_refdef.view.frustum[4].dist = m[15] - m[14];
5130 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5131 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5132 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5133 r_refdef.view.frustum[5].dist = m[15] + m[14];
5136 if (r_refdef.view.useperspective)
5138 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5139 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]);
5140 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]);
5141 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]);
5142 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]);
5144 // then the normals from the corners relative to origin
5145 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5146 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5147 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5148 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5150 // in a NORMAL view, forward cross left == up
5151 // in a REFLECTED view, forward cross left == down
5152 // so our cross products above need to be adjusted for a left handed coordinate system
5153 CrossProduct(forward, left, v);
5154 if(DotProduct(v, up) < 0)
5156 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5157 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5158 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5159 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5162 // Leaving those out was a mistake, those were in the old code, and they
5163 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5164 // I couldn't reproduce it after adding those normalizations. --blub
5165 VectorNormalize(r_refdef.view.frustum[0].normal);
5166 VectorNormalize(r_refdef.view.frustum[1].normal);
5167 VectorNormalize(r_refdef.view.frustum[2].normal);
5168 VectorNormalize(r_refdef.view.frustum[3].normal);
5170 // make the corners absolute
5171 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5172 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5173 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5174 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5177 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5179 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5180 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5181 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5182 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5183 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5187 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5188 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5189 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5190 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5191 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5192 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5193 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5194 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5195 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5196 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5198 r_refdef.view.numfrustumplanes = 5;
5200 if (r_refdef.view.useclipplane)
5202 r_refdef.view.numfrustumplanes = 6;
5203 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5206 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5207 PlaneClassify(r_refdef.view.frustum + i);
5209 // LordHavoc: note to all quake engine coders, Quake had a special case
5210 // for 90 degrees which assumed a square view (wrong), so I removed it,
5211 // Quake2 has it disabled as well.
5213 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5214 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5215 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5216 //PlaneClassify(&frustum[0]);
5218 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5219 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5220 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5221 //PlaneClassify(&frustum[1]);
5223 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5224 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5225 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5226 //PlaneClassify(&frustum[2]);
5228 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5229 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5230 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5231 //PlaneClassify(&frustum[3]);
5234 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5235 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5236 //PlaneClassify(&frustum[4]);
5239 void R_View_UpdateWithScissor(const int *myscissor)
5241 R_Main_ResizeViewCache();
5242 R_View_SetFrustum(myscissor);
5243 R_View_WorldVisibility(r_refdef.view.useclipplane);
5244 R_View_UpdateEntityVisible();
5245 R_View_UpdateEntityLighting();
5248 void R_View_Update(void)
5250 R_Main_ResizeViewCache();
5251 R_View_SetFrustum(NULL);
5252 R_View_WorldVisibility(r_refdef.view.useclipplane);
5253 R_View_UpdateEntityVisible();
5254 R_View_UpdateEntityLighting();
5257 float viewscalefpsadjusted = 1.0f;
5259 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5261 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5262 scale = bound(0.03125f, scale, 1.0f);
5263 *outwidth = (int)ceil(width * scale);
5264 *outheight = (int)ceil(height * scale);
5267 void R_Mesh_SetMainRenderTargets(void)
5269 if (r_bloomstate.fbo_framebuffer)
5270 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5272 R_Mesh_ResetRenderTargets();
5275 void R_SetupView(qboolean allowwaterclippingplane)
5277 const float *customclipplane = NULL;
5279 int scaledwidth, scaledheight;
5280 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5282 // LordHavoc: couldn't figure out how to make this approach the
5283 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5284 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5285 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5286 dist = r_refdef.view.clipplane.dist;
5287 plane[0] = r_refdef.view.clipplane.normal[0];
5288 plane[1] = r_refdef.view.clipplane.normal[1];
5289 plane[2] = r_refdef.view.clipplane.normal[2];
5291 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5294 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5295 if (!r_refdef.view.useperspective)
5296 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);
5297 else if (vid.stencil && r_useinfinitefarclip.integer)
5298 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);
5300 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);
5301 R_Mesh_SetMainRenderTargets();
5302 R_SetViewport(&r_refdef.view.viewport);
5303 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5305 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5306 float screenplane[4];
5307 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5308 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5309 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5310 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5311 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5315 void R_EntityMatrix(const matrix4x4_t *matrix)
5317 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5319 gl_modelmatrixchanged = false;
5320 gl_modelmatrix = *matrix;
5321 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5322 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5323 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5324 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5326 switch(vid.renderpath)
5328 case RENDERPATH_D3D9:
5330 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5331 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5334 case RENDERPATH_D3D10:
5335 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5337 case RENDERPATH_D3D11:
5338 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5340 case RENDERPATH_GL11:
5341 case RENDERPATH_GL13:
5342 case RENDERPATH_GLES1:
5343 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5345 case RENDERPATH_SOFT:
5346 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5347 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5349 case RENDERPATH_GL20:
5350 case RENDERPATH_GLES2:
5351 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5352 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5358 void R_ResetViewRendering2D(void)
5360 r_viewport_t viewport;
5363 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5364 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);
5365 R_Mesh_ResetRenderTargets();
5366 R_SetViewport(&viewport);
5367 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5368 GL_Color(1, 1, 1, 1);
5369 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5370 GL_BlendFunc(GL_ONE, GL_ZERO);
5371 GL_ScissorTest(false);
5372 GL_DepthMask(false);
5373 GL_DepthRange(0, 1);
5374 GL_DepthTest(false);
5375 GL_DepthFunc(GL_LEQUAL);
5376 R_EntityMatrix(&identitymatrix);
5377 R_Mesh_ResetTextureState();
5378 GL_PolygonOffset(0, 0);
5379 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5380 switch(vid.renderpath)
5382 case RENDERPATH_GL11:
5383 case RENDERPATH_GL13:
5384 case RENDERPATH_GL20:
5385 case RENDERPATH_GLES1:
5386 case RENDERPATH_GLES2:
5387 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5389 case RENDERPATH_D3D9:
5390 case RENDERPATH_D3D10:
5391 case RENDERPATH_D3D11:
5392 case RENDERPATH_SOFT:
5395 GL_CullFace(GL_NONE);
5398 void R_ResetViewRendering3D(void)
5403 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5404 GL_Color(1, 1, 1, 1);
5405 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5406 GL_BlendFunc(GL_ONE, GL_ZERO);
5407 GL_ScissorTest(true);
5409 GL_DepthRange(0, 1);
5411 GL_DepthFunc(GL_LEQUAL);
5412 R_EntityMatrix(&identitymatrix);
5413 R_Mesh_ResetTextureState();
5414 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5415 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5416 switch(vid.renderpath)
5418 case RENDERPATH_GL11:
5419 case RENDERPATH_GL13:
5420 case RENDERPATH_GL20:
5421 case RENDERPATH_GLES1:
5422 case RENDERPATH_GLES2:
5423 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5425 case RENDERPATH_D3D9:
5426 case RENDERPATH_D3D10:
5427 case RENDERPATH_D3D11:
5428 case RENDERPATH_SOFT:
5431 GL_CullFace(r_refdef.view.cullface_back);
5436 R_RenderView_UpdateViewVectors
5439 static void R_RenderView_UpdateViewVectors(void)
5441 // break apart the view matrix into vectors for various purposes
5442 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5443 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5444 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5445 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5446 // make an inverted copy of the view matrix for tracking sprites
5447 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5450 void R_RenderScene(void);
5451 void R_RenderWaterPlanes(void);
5453 static void R_Water_StartFrame(void)
5456 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5457 r_waterstate_waterplane_t *p;
5459 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5462 switch(vid.renderpath)
5464 case RENDERPATH_GL20:
5465 case RENDERPATH_D3D9:
5466 case RENDERPATH_D3D10:
5467 case RENDERPATH_D3D11:
5468 case RENDERPATH_SOFT:
5469 case RENDERPATH_GLES2:
5471 case RENDERPATH_GL11:
5472 case RENDERPATH_GL13:
5473 case RENDERPATH_GLES1:
5477 // set waterwidth and waterheight to the water resolution that will be
5478 // used (often less than the screen resolution for faster rendering)
5479 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5481 // calculate desired texture sizes
5482 // can't use water if the card does not support the texture size
5483 if (!r_water.integer || r_showsurfaces.integer)
5484 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5485 else if (vid.support.arb_texture_non_power_of_two)
5487 texturewidth = waterwidth;
5488 textureheight = waterheight;
5489 camerawidth = waterwidth;
5490 cameraheight = waterheight;
5494 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5495 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5496 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5497 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5500 // allocate textures as needed
5501 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5503 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5504 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5506 if (p->texture_refraction)
5507 R_FreeTexture(p->texture_refraction);
5508 p->texture_refraction = NULL;
5509 if (p->texture_reflection)
5510 R_FreeTexture(p->texture_reflection);
5511 p->texture_reflection = NULL;
5512 if (p->texture_camera)
5513 R_FreeTexture(p->texture_camera);
5514 p->texture_camera = NULL;
5516 memset(&r_waterstate, 0, sizeof(r_waterstate));
5517 r_waterstate.texturewidth = texturewidth;
5518 r_waterstate.textureheight = textureheight;
5519 r_waterstate.camerawidth = camerawidth;
5520 r_waterstate.cameraheight = cameraheight;
5523 if (r_waterstate.texturewidth)
5525 int scaledwidth, scaledheight;
5527 r_waterstate.enabled = true;
5529 // when doing a reduced render (HDR) we want to use a smaller area
5530 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5531 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5532 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5534 // set up variables that will be used in shader setup
5535 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5536 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5537 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5538 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5541 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5542 r_waterstate.numwaterplanes = 0;
5545 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5547 int triangleindex, planeindex;
5553 r_waterstate_waterplane_t *p;
5554 texture_t *t = R_GetCurrentTexture(surface->texture);
5556 // just use the first triangle with a valid normal for any decisions
5557 VectorClear(normal);
5558 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5560 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5561 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5562 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5563 TriangleNormal(vert[0], vert[1], vert[2], normal);
5564 if (VectorLength2(normal) >= 0.001)
5568 VectorCopy(normal, plane.normal);
5569 VectorNormalize(plane.normal);
5570 plane.dist = DotProduct(vert[0], plane.normal);
5571 PlaneClassify(&plane);
5572 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5574 // skip backfaces (except if nocullface is set)
5575 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5577 VectorNegate(plane.normal, plane.normal);
5579 PlaneClassify(&plane);
5583 // find a matching plane if there is one
5584 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5585 if(p->camera_entity == t->camera_entity)
5586 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5588 if (planeindex >= r_waterstate.maxwaterplanes)
5589 return; // nothing we can do, out of planes
5591 // if this triangle does not fit any known plane rendered this frame, add one
5592 if (planeindex >= r_waterstate.numwaterplanes)
5594 // store the new plane
5595 r_waterstate.numwaterplanes++;
5597 // clear materialflags and pvs
5598 p->materialflags = 0;
5599 p->pvsvalid = false;
5600 p->camera_entity = t->camera_entity;
5601 VectorCopy(surface->mins, p->mins);
5602 VectorCopy(surface->maxs, p->maxs);
5607 p->mins[0] = min(p->mins[0], surface->mins[0]);
5608 p->mins[1] = min(p->mins[1], surface->mins[1]);
5609 p->mins[2] = min(p->mins[2], surface->mins[2]);
5610 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5611 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5612 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5614 // merge this surface's materialflags into the waterplane
5615 p->materialflags |= t->currentmaterialflags;
5616 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5618 // merge this surface's PVS into the waterplane
5619 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5620 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5621 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5623 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5629 extern cvar_t r_drawparticles;
5630 extern cvar_t r_drawdecals;
5632 static void R_Water_ProcessPlanes(void)
5635 r_refdef_view_t originalview;
5636 r_refdef_view_t myview;
5637 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;
5638 r_waterstate_waterplane_t *p;
5641 originalview = r_refdef.view;
5643 // lowquality hack, temporarily shut down some cvars and restore afterwards
5644 qualityreduction = r_water_lowquality.integer;
5645 if (qualityreduction > 0)
5647 if (qualityreduction >= 1)
5649 old_r_shadows = r_shadows.integer;
5650 old_r_worldrtlight = r_shadow_realtime_world.integer;
5651 old_r_dlight = r_shadow_realtime_dlight.integer;
5652 Cvar_SetValueQuick(&r_shadows, 0);
5653 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5654 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5656 if (qualityreduction >= 2)
5658 old_r_dynamic = r_dynamic.integer;
5659 old_r_particles = r_drawparticles.integer;
5660 old_r_decals = r_drawdecals.integer;
5661 Cvar_SetValueQuick(&r_dynamic, 0);
5662 Cvar_SetValueQuick(&r_drawparticles, 0);
5663 Cvar_SetValueQuick(&r_drawdecals, 0);
5667 // make sure enough textures are allocated
5668 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5670 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5672 if (!p->texture_refraction)
5673 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);
5674 if (!p->texture_refraction)
5677 else if (p->materialflags & MATERIALFLAG_CAMERA)
5679 if (!p->texture_camera)
5680 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);
5681 if (!p->texture_camera)
5685 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5687 if (!p->texture_reflection)
5688 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);
5689 if (!p->texture_reflection)
5695 r_refdef.view = originalview;
5696 r_refdef.view.showdebug = false;
5697 r_refdef.view.width = r_waterstate.waterwidth;
5698 r_refdef.view.height = r_waterstate.waterheight;
5699 r_refdef.view.useclipplane = true;
5700 myview = r_refdef.view;
5701 r_waterstate.renderingscene = true;
5702 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5704 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5706 r_refdef.view = myview;
5707 if(r_water_scissormode.integer)
5710 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5711 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5714 // render reflected scene and copy into texture
5715 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5716 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5717 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5718 r_refdef.view.clipplane = p->plane;
5719 // reverse the cullface settings for this render
5720 r_refdef.view.cullface_front = GL_FRONT;
5721 r_refdef.view.cullface_back = GL_BACK;
5722 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5724 r_refdef.view.usecustompvs = true;
5726 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5728 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5731 R_ResetViewRendering3D();
5732 R_ClearScreen(r_refdef.fogenabled);
5733 if(r_water_scissormode.integer & 2)
5734 R_View_UpdateWithScissor(myscissor);
5737 if(r_water_scissormode.integer & 1)
5738 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5741 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);
5744 // render the normal view scene and copy into texture
5745 // (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)
5746 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5748 r_refdef.view = myview;
5749 if(r_water_scissormode.integer)
5752 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5753 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5756 r_waterstate.renderingrefraction = true;
5758 r_refdef.view.clipplane = p->plane;
5759 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5760 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5762 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5764 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5765 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5766 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5767 R_RenderView_UpdateViewVectors();
5768 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5770 r_refdef.view.usecustompvs = true;
5771 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);
5775 PlaneClassify(&r_refdef.view.clipplane);
5777 R_ResetViewRendering3D();
5778 R_ClearScreen(r_refdef.fogenabled);
5779 if(r_water_scissormode.integer & 2)
5780 R_View_UpdateWithScissor(myscissor);
5783 if(r_water_scissormode.integer & 1)
5784 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5787 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);
5788 r_waterstate.renderingrefraction = false;
5790 else if (p->materialflags & MATERIALFLAG_CAMERA)
5792 r_refdef.view = myview;
5794 r_refdef.view.clipplane = p->plane;
5795 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5796 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5798 r_refdef.view.width = r_waterstate.camerawidth;
5799 r_refdef.view.height = r_waterstate.cameraheight;
5800 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5801 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5803 if(p->camera_entity)
5805 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5806 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5809 // note: all of the view is used for displaying... so
5810 // there is no use in scissoring
5812 // reverse the cullface settings for this render
5813 r_refdef.view.cullface_front = GL_FRONT;
5814 r_refdef.view.cullface_back = GL_BACK;
5815 // also reverse the view matrix
5816 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
5817 R_RenderView_UpdateViewVectors();
5818 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5820 r_refdef.view.usecustompvs = true;
5821 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);
5824 // camera needs no clipplane
5825 r_refdef.view.useclipplane = false;
5827 PlaneClassify(&r_refdef.view.clipplane);
5829 R_ResetViewRendering3D();
5830 R_ClearScreen(r_refdef.fogenabled);
5834 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);
5835 r_waterstate.renderingrefraction = false;
5839 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5840 r_waterstate.renderingscene = false;
5841 r_refdef.view = originalview;
5842 R_ResetViewRendering3D();
5843 R_ClearScreen(r_refdef.fogenabled);
5847 r_refdef.view = originalview;
5848 r_waterstate.renderingscene = false;
5849 Cvar_SetValueQuick(&r_water, 0);
5850 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5852 // lowquality hack, restore cvars
5853 if (qualityreduction > 0)
5855 if (qualityreduction >= 1)
5857 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5858 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5859 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5861 if (qualityreduction >= 2)
5863 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5864 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5865 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5870 void R_Bloom_StartFrame(void)
5872 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5873 int viewwidth, viewheight;
5876 if (r_viewscale_fpsscaling.integer)
5878 double actualframetime;
5879 double targetframetime;
5881 actualframetime = r_refdef.lastdrawscreentime;
5882 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5883 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5884 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5885 if (r_viewscale_fpsscaling_stepsize.value > 0)
5886 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5887 viewscalefpsadjusted += adjust;
5888 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5891 viewscalefpsadjusted = 1.0f;
5893 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5895 switch(vid.renderpath)
5897 case RENDERPATH_GL20:
5898 case RENDERPATH_D3D9:
5899 case RENDERPATH_D3D10:
5900 case RENDERPATH_D3D11:
5901 case RENDERPATH_SOFT:
5902 case RENDERPATH_GLES2:
5904 case RENDERPATH_GL11:
5905 case RENDERPATH_GL13:
5906 case RENDERPATH_GLES1:
5910 // set bloomwidth and bloomheight to the bloom resolution that will be
5911 // used (often less than the screen resolution for faster rendering)
5912 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5913 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5914 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5915 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5916 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5918 // calculate desired texture sizes
5919 if (vid.support.arb_texture_non_power_of_two)
5921 screentexturewidth = vid.width;
5922 screentextureheight = vid.height;
5923 bloomtexturewidth = r_bloomstate.bloomwidth;
5924 bloomtextureheight = r_bloomstate.bloomheight;
5928 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5929 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5930 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5931 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5934 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))
5936 Cvar_SetValueQuick(&r_hdr, 0);
5937 Cvar_SetValueQuick(&r_bloom, 0);
5938 Cvar_SetValueQuick(&r_motionblur, 0);
5939 Cvar_SetValueQuick(&r_damageblur, 0);
5942 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)
5943 screentexturewidth = screentextureheight = 0;
5944 if (!r_hdr.integer && !r_bloom.integer)
5945 bloomtexturewidth = bloomtextureheight = 0;
5947 textype = TEXTYPE_COLORBUFFER;
5948 switch (vid.renderpath)
5950 case RENDERPATH_GL20:
5951 case RENDERPATH_GLES2:
5952 if (vid.support.ext_framebuffer_object)
5954 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5955 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5958 case RENDERPATH_GL11:
5959 case RENDERPATH_GL13:
5960 case RENDERPATH_GLES1:
5961 case RENDERPATH_D3D9:
5962 case RENDERPATH_D3D10:
5963 case RENDERPATH_D3D11:
5964 case RENDERPATH_SOFT:
5968 // allocate textures as needed
5969 if (r_bloomstate.screentexturewidth != screentexturewidth
5970 || r_bloomstate.screentextureheight != screentextureheight
5971 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5972 || r_bloomstate.bloomtextureheight != bloomtextureheight
5973 || r_bloomstate.texturetype != textype
5974 || r_bloomstate.viewfbo != r_viewfbo.integer)
5976 if (r_bloomstate.texture_bloom)
5977 R_FreeTexture(r_bloomstate.texture_bloom);
5978 r_bloomstate.texture_bloom = NULL;
5979 if (r_bloomstate.texture_screen)
5980 R_FreeTexture(r_bloomstate.texture_screen);
5981 r_bloomstate.texture_screen = NULL;
5982 if (r_bloomstate.fbo_framebuffer)
5983 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5984 r_bloomstate.fbo_framebuffer = 0;
5985 if (r_bloomstate.texture_framebuffercolor)
5986 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5987 r_bloomstate.texture_framebuffercolor = NULL;
5988 if (r_bloomstate.texture_framebufferdepth)
5989 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5990 r_bloomstate.texture_framebufferdepth = NULL;
5991 r_bloomstate.screentexturewidth = screentexturewidth;
5992 r_bloomstate.screentextureheight = screentextureheight;
5993 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5994 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);
5995 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5997 // FIXME: choose depth bits based on a cvar
5998 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5999 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);
6000 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6001 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6002 // render depth into one texture and normalmap into the other
6006 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6007 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6008 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6009 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6010 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6013 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6014 r_bloomstate.bloomtextureheight = bloomtextureheight;
6015 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6016 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);
6017 r_bloomstate.viewfbo = r_viewfbo.integer;
6018 r_bloomstate.texturetype = textype;
6021 // when doing a reduced render (HDR) we want to use a smaller area
6022 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6023 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6024 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6025 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6026 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6028 // set up a texcoord array for the full resolution screen image
6029 // (we have to keep this around to copy back during final render)
6030 r_bloomstate.screentexcoord2f[0] = 0;
6031 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6032 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6033 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6034 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6035 r_bloomstate.screentexcoord2f[5] = 0;
6036 r_bloomstate.screentexcoord2f[6] = 0;
6037 r_bloomstate.screentexcoord2f[7] = 0;
6039 // set up a texcoord array for the reduced resolution bloom image
6040 // (which will be additive blended over the screen image)
6041 r_bloomstate.bloomtexcoord2f[0] = 0;
6042 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6043 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6044 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6045 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6046 r_bloomstate.bloomtexcoord2f[5] = 0;
6047 r_bloomstate.bloomtexcoord2f[6] = 0;
6048 r_bloomstate.bloomtexcoord2f[7] = 0;
6050 switch(vid.renderpath)
6052 case RENDERPATH_GL11:
6053 case RENDERPATH_GL13:
6054 case RENDERPATH_GL20:
6055 case RENDERPATH_SOFT:
6056 case RENDERPATH_GLES1:
6057 case RENDERPATH_GLES2:
6059 case RENDERPATH_D3D9:
6060 case RENDERPATH_D3D10:
6061 case RENDERPATH_D3D11:
6064 for (i = 0;i < 4;i++)
6066 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6067 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6068 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6069 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6075 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6077 r_bloomstate.enabled = true;
6078 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6081 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);
6083 if (r_bloomstate.fbo_framebuffer)
6084 r_refdef.view.clear = true;
6087 void R_Bloom_CopyBloomTexture(float colorscale)
6089 r_refdef.stats.bloom++;
6091 // scale down screen texture to the bloom texture size
6093 R_Mesh_SetMainRenderTargets();
6094 R_SetViewport(&r_bloomstate.viewport);
6095 GL_BlendFunc(GL_ONE, GL_ZERO);
6096 GL_Color(colorscale, colorscale, colorscale, 1);
6097 // 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...
6098 switch(vid.renderpath)
6100 case RENDERPATH_GL11:
6101 case RENDERPATH_GL13:
6102 case RENDERPATH_GL20:
6103 case RENDERPATH_GLES1:
6104 case RENDERPATH_GLES2:
6105 case RENDERPATH_SOFT:
6106 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6108 case RENDERPATH_D3D9:
6109 case RENDERPATH_D3D10:
6110 case RENDERPATH_D3D11:
6111 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6114 // TODO: do boxfilter scale-down in shader?
6115 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6116 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6117 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6119 // we now have a bloom image in the framebuffer
6120 // copy it into the bloom image texture for later processing
6121 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);
6122 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6125 void R_Bloom_CopyHDRTexture(void)
6127 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);
6128 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6131 void R_Bloom_MakeTexture(void)
6134 float xoffset, yoffset, r, brighten;
6136 r_refdef.stats.bloom++;
6138 R_ResetViewRendering2D();
6140 // we have a bloom image in the framebuffer
6142 R_SetViewport(&r_bloomstate.viewport);
6144 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6147 r = bound(0, r_bloom_colorexponent.value / x, 1);
6148 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6150 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6151 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, 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 // copy the vertically blurred bloom view to a texture
6156 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);
6157 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6160 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6161 brighten = r_bloom_brighten.value;
6162 if (r_bloomstate.hdr)
6163 brighten *= r_hdr_range.value;
6164 brighten = sqrt(brighten);
6166 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6167 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6169 for (dir = 0;dir < 2;dir++)
6171 // blend on at multiple vertical offsets to achieve a vertical blur
6172 // TODO: do offset blends using GLSL
6173 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6174 GL_BlendFunc(GL_ONE, GL_ZERO);
6175 for (x = -range;x <= range;x++)
6177 if (!dir){xoffset = 0;yoffset = x;}
6178 else {xoffset = x;yoffset = 0;}
6179 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6180 yoffset /= (float)r_bloomstate.bloomtextureheight;
6181 // compute a texcoord array with the specified x and y offset
6182 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6183 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6184 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6185 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6186 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6187 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6188 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6189 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6190 // this r value looks like a 'dot' particle, fading sharply to
6191 // black at the edges
6192 // (probably not realistic but looks good enough)
6193 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6194 //r = brighten/(range*2+1);
6195 r = brighten / (range * 2 + 1);
6197 r *= (1 - x*x/(float)(range*range));
6198 GL_Color(r, r, r, 1);
6199 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6200 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6201 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6202 GL_BlendFunc(GL_ONE, GL_ONE);
6205 // copy the vertically blurred bloom view to a texture
6206 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);
6207 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6211 void R_HDR_RenderBloomTexture(void)
6213 int oldwidth, oldheight;
6214 float oldcolorscale;
6215 qboolean oldwaterstate;
6217 oldwaterstate = r_waterstate.enabled;
6218 oldcolorscale = r_refdef.view.colorscale;
6219 oldwidth = r_refdef.view.width;
6220 oldheight = r_refdef.view.height;
6221 r_refdef.view.width = r_bloomstate.bloomwidth;
6222 r_refdef.view.height = r_bloomstate.bloomheight;
6224 if(r_hdr.integer < 2)
6225 r_waterstate.enabled = false;
6227 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6228 // TODO: add exposure compensation features
6229 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6231 r_refdef.view.showdebug = false;
6232 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6234 R_ResetViewRendering3D();
6236 R_ClearScreen(r_refdef.fogenabled);
6237 if (r_timereport_active)
6238 R_TimeReport("HDRclear");
6241 if (r_timereport_active)
6242 R_TimeReport("visibility");
6244 // only do secondary renders with HDR if r_hdr is 2 or higher
6245 r_waterstate.numwaterplanes = 0;
6246 if (r_waterstate.enabled)
6247 R_RenderWaterPlanes();
6249 r_refdef.view.showdebug = true;
6251 r_waterstate.numwaterplanes = 0;
6253 R_ResetViewRendering2D();
6255 R_Bloom_CopyHDRTexture();
6256 R_Bloom_MakeTexture();
6258 // restore the view settings
6259 r_waterstate.enabled = oldwaterstate;
6260 r_refdef.view.width = oldwidth;
6261 r_refdef.view.height = oldheight;
6262 r_refdef.view.colorscale = oldcolorscale;
6264 R_ResetViewRendering3D();
6266 R_ClearScreen(r_refdef.fogenabled);
6267 if (r_timereport_active)
6268 R_TimeReport("viewclear");
6271 static void R_BlendView(void)
6273 unsigned int permutation;
6274 float uservecs[4][4];
6276 switch (vid.renderpath)
6278 case RENDERPATH_GL20:
6279 case RENDERPATH_D3D9:
6280 case RENDERPATH_D3D10:
6281 case RENDERPATH_D3D11:
6282 case RENDERPATH_SOFT:
6283 case RENDERPATH_GLES2:
6285 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6286 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6287 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6288 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6289 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6291 if (r_bloomstate.texture_screen)
6293 // make sure the buffer is available
6294 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6296 R_ResetViewRendering2D();
6297 R_Mesh_SetMainRenderTargets();
6299 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6301 // declare variables
6302 float blur_factor, blur_mouseaccel, blur_velocity;
6303 static float blur_average;
6304 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6306 // set a goal for the factoring
6307 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6308 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6309 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6310 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6311 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6312 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6314 // from the goal, pick an averaged value between goal and last value
6315 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6316 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6318 // enforce minimum amount of blur
6319 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6321 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6323 // calculate values into a standard alpha
6324 cl.motionbluralpha = 1 - exp(-
6326 (r_motionblur.value * blur_factor / 80)
6328 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6331 max(0.0001, cl.time - cl.oldtime) // fps independent
6334 // randomization for the blur value to combat persistent ghosting
6335 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6336 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6339 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6341 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6342 GL_Color(1, 1, 1, cl.motionbluralpha);
6343 switch(vid.renderpath)
6345 case RENDERPATH_GL11:
6346 case RENDERPATH_GL13:
6347 case RENDERPATH_GL20:
6348 case RENDERPATH_GLES1:
6349 case RENDERPATH_GLES2:
6350 case RENDERPATH_SOFT:
6351 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6353 case RENDERPATH_D3D9:
6354 case RENDERPATH_D3D10:
6355 case RENDERPATH_D3D11:
6356 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6359 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6360 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6361 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6364 // updates old view angles for next pass
6365 VectorCopy(cl.viewangles, blur_oldangles);
6368 // copy view into the screen texture
6369 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);
6370 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6372 else if (!r_bloomstate.texture_bloom)
6374 // we may still have to do view tint...
6375 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6377 // apply a color tint to the whole view
6378 R_ResetViewRendering2D();
6379 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6380 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6381 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6382 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6383 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6385 break; // no screen processing, no bloom, skip it
6388 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6390 // render simple bloom effect
6391 // copy the screen and shrink it and darken it for the bloom process
6392 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6393 // make the bloom texture
6394 R_Bloom_MakeTexture();
6397 #if _MSC_VER >= 1400
6398 #define sscanf sscanf_s
6400 memset(uservecs, 0, sizeof(uservecs));
6401 if (r_glsl_postprocess_uservec1_enable.integer)
6402 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6403 if (r_glsl_postprocess_uservec2_enable.integer)
6404 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6405 if (r_glsl_postprocess_uservec3_enable.integer)
6406 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6407 if (r_glsl_postprocess_uservec4_enable.integer)
6408 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6410 R_ResetViewRendering2D();
6411 GL_Color(1, 1, 1, 1);
6412 GL_BlendFunc(GL_ONE, GL_ZERO);
6414 switch(vid.renderpath)
6416 case RENDERPATH_GL20:
6417 case RENDERPATH_GLES2:
6418 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6419 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6420 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6421 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6422 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6423 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]);
6424 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6425 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]);
6426 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]);
6427 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]);
6428 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]);
6429 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6430 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6431 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);
6433 case RENDERPATH_D3D9:
6435 // 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...
6436 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6437 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6438 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6439 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6440 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6441 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6442 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6443 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6444 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6445 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6446 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6447 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6448 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6449 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6452 case RENDERPATH_D3D10:
6453 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6455 case RENDERPATH_D3D11:
6456 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6458 case RENDERPATH_SOFT:
6459 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6460 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6461 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6462 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6463 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6464 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6465 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6466 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6467 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6468 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6469 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6470 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6471 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6472 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6477 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6478 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6480 case RENDERPATH_GL11:
6481 case RENDERPATH_GL13:
6482 case RENDERPATH_GLES1:
6483 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6485 // apply a color tint to the whole view
6486 R_ResetViewRendering2D();
6487 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6488 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6489 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6490 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6491 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6497 matrix4x4_t r_waterscrollmatrix;
6499 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6501 if (r_refdef.fog_density)
6503 r_refdef.fogcolor[0] = r_refdef.fog_red;
6504 r_refdef.fogcolor[1] = r_refdef.fog_green;
6505 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6507 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6508 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6509 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6510 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6514 VectorCopy(r_refdef.fogcolor, fogvec);
6515 // color.rgb *= ContrastBoost * SceneBrightness;
6516 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6517 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6518 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6519 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6524 void R_UpdateVariables(void)
6528 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6530 r_refdef.farclip = r_farclip_base.value;
6531 if (r_refdef.scene.worldmodel)
6532 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6533 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6535 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6536 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6537 r_refdef.polygonfactor = 0;
6538 r_refdef.polygonoffset = 0;
6539 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6540 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6542 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6543 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6544 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6545 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6546 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6547 if (FAKELIGHT_ENABLED)
6549 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6551 if (r_showsurfaces.integer)
6553 r_refdef.scene.rtworld = false;
6554 r_refdef.scene.rtworldshadows = false;
6555 r_refdef.scene.rtdlight = false;
6556 r_refdef.scene.rtdlightshadows = false;
6557 r_refdef.lightmapintensity = 0;
6560 if (gamemode == GAME_NEHAHRA)
6562 if (gl_fogenable.integer)
6564 r_refdef.oldgl_fogenable = true;
6565 r_refdef.fog_density = gl_fogdensity.value;
6566 r_refdef.fog_red = gl_fogred.value;
6567 r_refdef.fog_green = gl_foggreen.value;
6568 r_refdef.fog_blue = gl_fogblue.value;
6569 r_refdef.fog_alpha = 1;
6570 r_refdef.fog_start = 0;
6571 r_refdef.fog_end = gl_skyclip.value;
6572 r_refdef.fog_height = 1<<30;
6573 r_refdef.fog_fadedepth = 128;
6575 else if (r_refdef.oldgl_fogenable)
6577 r_refdef.oldgl_fogenable = false;
6578 r_refdef.fog_density = 0;
6579 r_refdef.fog_red = 0;
6580 r_refdef.fog_green = 0;
6581 r_refdef.fog_blue = 0;
6582 r_refdef.fog_alpha = 0;
6583 r_refdef.fog_start = 0;
6584 r_refdef.fog_end = 0;
6585 r_refdef.fog_height = 1<<30;
6586 r_refdef.fog_fadedepth = 128;
6590 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6591 r_refdef.fog_start = max(0, r_refdef.fog_start);
6592 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6594 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6596 if (r_refdef.fog_density && r_drawfog.integer)
6598 r_refdef.fogenabled = true;
6599 // this is the point where the fog reaches 0.9986 alpha, which we
6600 // consider a good enough cutoff point for the texture
6601 // (0.9986 * 256 == 255.6)
6602 if (r_fog_exp2.integer)
6603 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6605 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6606 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6607 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6608 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6609 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6610 R_BuildFogHeightTexture();
6611 // fog color was already set
6612 // update the fog texture
6613 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)
6614 R_BuildFogTexture();
6615 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6616 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6619 r_refdef.fogenabled = false;
6621 switch(vid.renderpath)
6623 case RENDERPATH_GL20:
6624 case RENDERPATH_D3D9:
6625 case RENDERPATH_D3D10:
6626 case RENDERPATH_D3D11:
6627 case RENDERPATH_SOFT:
6628 case RENDERPATH_GLES2:
6629 if(v_glslgamma.integer && !vid_gammatables_trivial)
6631 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6633 // build GLSL gamma texture
6634 #define RAMPWIDTH 256
6635 unsigned short ramp[RAMPWIDTH * 3];
6636 unsigned char rampbgr[RAMPWIDTH][4];
6639 r_texture_gammaramps_serial = vid_gammatables_serial;
6641 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6642 for(i = 0; i < RAMPWIDTH; ++i)
6644 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6645 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6646 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6649 if (r_texture_gammaramps)
6651 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6655 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6661 // remove GLSL gamma texture
6664 case RENDERPATH_GL11:
6665 case RENDERPATH_GL13:
6666 case RENDERPATH_GLES1:
6671 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6672 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6678 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6679 if( scenetype != r_currentscenetype ) {
6680 // store the old scenetype
6681 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6682 r_currentscenetype = scenetype;
6683 // move in the new scene
6684 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6693 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6695 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6696 if( scenetype == r_currentscenetype ) {
6697 return &r_refdef.scene;
6699 return &r_scenes_store[ scenetype ];
6708 int dpsoftrast_test;
6709 extern void R_Shadow_UpdateBounceGridTexture(void);
6710 extern cvar_t r_shadow_bouncegrid;
6711 void R_RenderView(void)
6713 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6715 dpsoftrast_test = r_test.integer;
6717 if (r_timereport_active)
6718 R_TimeReport("start");
6719 r_textureframe++; // used only by R_GetCurrentTexture
6720 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6722 if(R_CompileShader_CheckStaticParms())
6725 if (!r_drawentities.integer)
6726 r_refdef.scene.numentities = 0;
6728 R_AnimCache_ClearCache();
6729 R_FrameData_NewFrame();
6731 /* adjust for stereo display */
6732 if(R_Stereo_Active())
6734 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);
6735 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6738 if (r_refdef.view.isoverlay)
6740 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6741 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6742 R_TimeReport("depthclear");
6744 r_refdef.view.showdebug = false;
6746 r_waterstate.enabled = false;
6747 r_waterstate.numwaterplanes = 0;
6751 r_refdef.view.matrix = originalmatrix;
6757 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6759 r_refdef.view.matrix = originalmatrix;
6760 return; //Host_Error ("R_RenderView: NULL worldmodel");
6763 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6765 R_RenderView_UpdateViewVectors();
6767 R_Shadow_UpdateWorldLightSelection();
6769 R_Bloom_StartFrame();
6770 R_Water_StartFrame();
6773 if (r_timereport_active)
6774 R_TimeReport("viewsetup");
6776 R_ResetViewRendering3D();
6778 if (r_refdef.view.clear || r_refdef.fogenabled)
6780 R_ClearScreen(r_refdef.fogenabled);
6781 if (r_timereport_active)
6782 R_TimeReport("viewclear");
6784 r_refdef.view.clear = true;
6786 // this produces a bloom texture to be used in R_BlendView() later
6787 if (r_bloomstate.hdr)
6789 R_HDR_RenderBloomTexture();
6790 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6791 r_textureframe++; // used only by R_GetCurrentTexture
6794 r_refdef.view.showdebug = true;
6797 if (r_timereport_active)
6798 R_TimeReport("visibility");
6800 R_Shadow_UpdateBounceGridTexture();
6801 if (r_timereport_active && r_shadow_bouncegrid.integer)
6802 R_TimeReport("bouncegrid");
6804 r_waterstate.numwaterplanes = 0;
6805 if (r_waterstate.enabled)
6806 R_RenderWaterPlanes();
6809 r_waterstate.numwaterplanes = 0;
6812 if (r_timereport_active)
6813 R_TimeReport("blendview");
6815 GL_Scissor(0, 0, vid.width, vid.height);
6816 GL_ScissorTest(false);
6818 r_refdef.view.matrix = originalmatrix;
6823 void R_RenderWaterPlanes(void)
6825 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6827 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6828 if (r_timereport_active)
6829 R_TimeReport("waterworld");
6832 // don't let sound skip if going slow
6833 if (r_refdef.scene.extraupdate)
6836 R_DrawModelsAddWaterPlanes();
6837 if (r_timereport_active)
6838 R_TimeReport("watermodels");
6840 if (r_waterstate.numwaterplanes)
6842 R_Water_ProcessPlanes();
6843 if (r_timereport_active)
6844 R_TimeReport("waterscenes");
6848 extern void R_DrawLightningBeams (void);
6849 extern void VM_CL_AddPolygonsToMeshQueue (void);
6850 extern void R_DrawPortals (void);
6851 extern cvar_t cl_locs_show;
6852 static void R_DrawLocs(void);
6853 static void R_DrawEntityBBoxes(void);
6854 static void R_DrawModelDecals(void);
6855 extern void R_DrawModelShadows(void);
6856 extern void R_DrawModelShadowMaps(void);
6857 extern cvar_t cl_decals_newsystem;
6858 extern qboolean r_shadow_usingdeferredprepass;
6859 void R_RenderScene(void)
6861 qboolean shadowmapping = false;
6863 if (r_timereport_active)
6864 R_TimeReport("beginscene");
6866 r_refdef.stats.renders++;
6870 // don't let sound skip if going slow
6871 if (r_refdef.scene.extraupdate)
6874 R_MeshQueue_BeginScene();
6878 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);
6880 if (r_timereport_active)
6881 R_TimeReport("skystartframe");
6883 if (cl.csqc_vidvars.drawworld)
6885 // don't let sound skip if going slow
6886 if (r_refdef.scene.extraupdate)
6889 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6891 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6892 if (r_timereport_active)
6893 R_TimeReport("worldsky");
6896 if (R_DrawBrushModelsSky() && r_timereport_active)
6897 R_TimeReport("bmodelsky");
6899 if (skyrendermasked && skyrenderlater)
6901 // we have to force off the water clipping plane while rendering sky
6905 if (r_timereport_active)
6906 R_TimeReport("sky");
6910 R_AnimCache_CacheVisibleEntities();
6911 if (r_timereport_active)
6912 R_TimeReport("animation");
6914 R_Shadow_PrepareLights();
6915 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6916 R_Shadow_PrepareModelShadows();
6917 if (r_timereport_active)
6918 R_TimeReport("preparelights");
6920 if (R_Shadow_ShadowMappingEnabled())
6921 shadowmapping = true;
6923 if (r_shadow_usingdeferredprepass)
6924 R_Shadow_DrawPrepass();
6926 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6928 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6929 if (r_timereport_active)
6930 R_TimeReport("worlddepth");
6932 if (r_depthfirst.integer >= 2)
6934 R_DrawModelsDepth();
6935 if (r_timereport_active)
6936 R_TimeReport("modeldepth");
6939 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6941 R_DrawModelShadowMaps();
6942 R_ResetViewRendering3D();
6943 // don't let sound skip if going slow
6944 if (r_refdef.scene.extraupdate)
6948 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6950 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6951 if (r_timereport_active)
6952 R_TimeReport("world");
6955 // don't let sound skip if going slow
6956 if (r_refdef.scene.extraupdate)
6960 if (r_timereport_active)
6961 R_TimeReport("models");
6963 // don't let sound skip if going slow
6964 if (r_refdef.scene.extraupdate)
6967 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6969 R_DrawModelShadows();
6970 R_ResetViewRendering3D();
6971 // don't let sound skip if going slow
6972 if (r_refdef.scene.extraupdate)
6976 if (!r_shadow_usingdeferredprepass)
6978 R_Shadow_DrawLights();
6979 if (r_timereport_active)
6980 R_TimeReport("rtlights");
6983 // don't let sound skip if going slow
6984 if (r_refdef.scene.extraupdate)
6987 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6989 R_DrawModelShadows();
6990 R_ResetViewRendering3D();
6991 // don't let sound skip if going slow
6992 if (r_refdef.scene.extraupdate)
6996 if (cl.csqc_vidvars.drawworld)
6998 if (cl_decals_newsystem.integer)
7000 R_DrawModelDecals();
7001 if (r_timereport_active)
7002 R_TimeReport("modeldecals");
7007 if (r_timereport_active)
7008 R_TimeReport("decals");
7012 if (r_timereport_active)
7013 R_TimeReport("particles");
7016 if (r_timereport_active)
7017 R_TimeReport("explosions");
7019 R_DrawLightningBeams();
7020 if (r_timereport_active)
7021 R_TimeReport("lightning");
7024 VM_CL_AddPolygonsToMeshQueue();
7026 if (r_refdef.view.showdebug)
7028 if (cl_locs_show.integer)
7031 if (r_timereport_active)
7032 R_TimeReport("showlocs");
7035 if (r_drawportals.integer)
7038 if (r_timereport_active)
7039 R_TimeReport("portals");
7042 if (r_showbboxes.value > 0)
7044 R_DrawEntityBBoxes();
7045 if (r_timereport_active)
7046 R_TimeReport("bboxes");
7050 if (r_transparent.integer)
7052 R_MeshQueue_RenderTransparent();
7053 if (r_timereport_active)
7054 R_TimeReport("drawtrans");
7057 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))
7059 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7060 if (r_timereport_active)
7061 R_TimeReport("worlddebug");
7062 R_DrawModelsDebug();
7063 if (r_timereport_active)
7064 R_TimeReport("modeldebug");
7067 if (cl.csqc_vidvars.drawworld)
7069 R_Shadow_DrawCoronas();
7070 if (r_timereport_active)
7071 R_TimeReport("coronas");
7076 GL_DepthTest(false);
7077 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7078 GL_Color(1, 1, 1, 1);
7079 qglBegin(GL_POLYGON);
7080 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7081 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7082 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7083 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7085 qglBegin(GL_POLYGON);
7086 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]);
7087 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]);
7088 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]);
7089 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]);
7091 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7095 // don't let sound skip if going slow
7096 if (r_refdef.scene.extraupdate)
7099 R_ResetViewRendering2D();
7102 static const unsigned short bboxelements[36] =
7112 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7115 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7117 RSurf_ActiveWorldEntity();
7119 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7120 GL_DepthMask(false);
7121 GL_DepthRange(0, 1);
7122 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7123 // R_Mesh_ResetTextureState();
7125 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7126 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7127 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7128 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7129 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7130 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7131 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7132 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7133 R_FillColors(color4f, 8, cr, cg, cb, ca);
7134 if (r_refdef.fogenabled)
7136 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7138 f1 = RSurf_FogVertex(v);
7140 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7141 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7142 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7145 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7146 R_Mesh_ResetTextureState();
7147 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7148 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7151 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7155 prvm_edict_t *edict;
7156 prvm_prog_t *prog_save = prog;
7158 // this function draws bounding boxes of server entities
7162 GL_CullFace(GL_NONE);
7163 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7167 for (i = 0;i < numsurfaces;i++)
7169 edict = PRVM_EDICT_NUM(surfacelist[i]);
7170 switch ((int)PRVM_serveredictfloat(edict, solid))
7172 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7173 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7174 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7175 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7176 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7177 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7179 color[3] *= r_showbboxes.value;
7180 color[3] = bound(0, color[3], 1);
7181 GL_DepthTest(!r_showdisabledepthtest.integer);
7182 GL_CullFace(r_refdef.view.cullface_front);
7183 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7189 static void R_DrawEntityBBoxes(void)
7192 prvm_edict_t *edict;
7194 prvm_prog_t *prog_save = prog;
7196 // this function draws bounding boxes of server entities
7202 for (i = 0;i < prog->num_edicts;i++)
7204 edict = PRVM_EDICT_NUM(i);
7205 if (edict->priv.server->free)
7207 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7208 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7210 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7212 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7213 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7219 static const int nomodelelement3i[24] =
7231 static const unsigned short nomodelelement3s[24] =
7243 static const float nomodelvertex3f[6*3] =
7253 static const float nomodelcolor4f[6*4] =
7255 0.0f, 0.0f, 0.5f, 1.0f,
7256 0.0f, 0.0f, 0.5f, 1.0f,
7257 0.0f, 0.5f, 0.0f, 1.0f,
7258 0.0f, 0.5f, 0.0f, 1.0f,
7259 0.5f, 0.0f, 0.0f, 1.0f,
7260 0.5f, 0.0f, 0.0f, 1.0f
7263 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7269 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);
7271 // this is only called once per entity so numsurfaces is always 1, and
7272 // surfacelist is always {0}, so this code does not handle batches
7274 if (rsurface.ent_flags & RENDER_ADDITIVE)
7276 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7277 GL_DepthMask(false);
7279 else if (rsurface.colormod[3] < 1)
7281 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7282 GL_DepthMask(false);
7286 GL_BlendFunc(GL_ONE, GL_ZERO);
7289 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7290 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7291 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7292 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7293 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7294 for (i = 0, c = color4f;i < 6;i++, c += 4)
7296 c[0] *= rsurface.colormod[0];
7297 c[1] *= rsurface.colormod[1];
7298 c[2] *= rsurface.colormod[2];
7299 c[3] *= rsurface.colormod[3];
7301 if (r_refdef.fogenabled)
7303 for (i = 0, c = color4f;i < 6;i++, c += 4)
7305 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7307 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7308 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7309 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7312 // R_Mesh_ResetTextureState();
7313 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7314 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7315 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7318 void R_DrawNoModel(entity_render_t *ent)
7321 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7322 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7323 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7325 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7328 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7330 vec3_t right1, right2, diff, normal;
7332 VectorSubtract (org2, org1, normal);
7334 // calculate 'right' vector for start
7335 VectorSubtract (r_refdef.view.origin, org1, diff);
7336 CrossProduct (normal, diff, right1);
7337 VectorNormalize (right1);
7339 // calculate 'right' vector for end
7340 VectorSubtract (r_refdef.view.origin, org2, diff);
7341 CrossProduct (normal, diff, right2);
7342 VectorNormalize (right2);
7344 vert[ 0] = org1[0] + width * right1[0];
7345 vert[ 1] = org1[1] + width * right1[1];
7346 vert[ 2] = org1[2] + width * right1[2];
7347 vert[ 3] = org1[0] - width * right1[0];
7348 vert[ 4] = org1[1] - width * right1[1];
7349 vert[ 5] = org1[2] - width * right1[2];
7350 vert[ 6] = org2[0] - width * right2[0];
7351 vert[ 7] = org2[1] - width * right2[1];
7352 vert[ 8] = org2[2] - width * right2[2];
7353 vert[ 9] = org2[0] + width * right2[0];
7354 vert[10] = org2[1] + width * right2[1];
7355 vert[11] = org2[2] + width * right2[2];
7358 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)
7360 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7361 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7362 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7363 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7364 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7365 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7366 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7367 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7368 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7369 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7370 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7371 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7374 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7379 VectorSet(v, x, y, z);
7380 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7381 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7383 if (i == mesh->numvertices)
7385 if (mesh->numvertices < mesh->maxvertices)
7387 VectorCopy(v, vertex3f);
7388 mesh->numvertices++;
7390 return mesh->numvertices;
7396 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7400 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7401 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7402 e = mesh->element3i + mesh->numtriangles * 3;
7403 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7405 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7406 if (mesh->numtriangles < mesh->maxtriangles)
7411 mesh->numtriangles++;
7413 element[1] = element[2];
7417 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7421 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7422 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7423 e = mesh->element3i + mesh->numtriangles * 3;
7424 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7426 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7427 if (mesh->numtriangles < mesh->maxtriangles)
7432 mesh->numtriangles++;
7434 element[1] = element[2];
7438 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7439 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7441 int planenum, planenum2;
7444 mplane_t *plane, *plane2;
7446 double temppoints[2][256*3];
7447 // figure out how large a bounding box we need to properly compute this brush
7449 for (w = 0;w < numplanes;w++)
7450 maxdist = max(maxdist, fabs(planes[w].dist));
7451 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7452 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7453 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7457 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7458 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7460 if (planenum2 == planenum)
7462 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);
7465 if (tempnumpoints < 3)
7467 // generate elements forming a triangle fan for this polygon
7468 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7472 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)
7474 texturelayer_t *layer;
7475 layer = t->currentlayers + t->currentnumlayers++;
7477 layer->depthmask = depthmask;
7478 layer->blendfunc1 = blendfunc1;
7479 layer->blendfunc2 = blendfunc2;
7480 layer->texture = texture;
7481 layer->texmatrix = *matrix;
7482 layer->color[0] = r;
7483 layer->color[1] = g;
7484 layer->color[2] = b;
7485 layer->color[3] = a;
7488 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7490 if(parms[0] == 0 && parms[1] == 0)
7492 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7493 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7498 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7501 index = parms[2] + rsurface.shadertime * parms[3];
7502 index -= floor(index);
7503 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7506 case Q3WAVEFUNC_NONE:
7507 case Q3WAVEFUNC_NOISE:
7508 case Q3WAVEFUNC_COUNT:
7511 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7512 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7513 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7514 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7515 case Q3WAVEFUNC_TRIANGLE:
7517 f = index - floor(index);
7530 f = parms[0] + parms[1] * f;
7531 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7532 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7536 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7542 matrix4x4_t matrix, temp;
7543 switch(tcmod->tcmod)
7547 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7548 matrix = r_waterscrollmatrix;
7550 matrix = identitymatrix;
7552 case Q3TCMOD_ENTITYTRANSLATE:
7553 // this is used in Q3 to allow the gamecode to control texcoord
7554 // scrolling on the entity, which is not supported in darkplaces yet.
7555 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7557 case Q3TCMOD_ROTATE:
7558 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7559 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7560 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7563 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7565 case Q3TCMOD_SCROLL:
7566 // extra care is needed because of precision breakdown with large values of time
7567 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7568 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7569 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7571 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7572 w = (int) tcmod->parms[0];
7573 h = (int) tcmod->parms[1];
7574 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7576 idx = (int) floor(f * w * h);
7577 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7579 case Q3TCMOD_STRETCH:
7580 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7581 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7583 case Q3TCMOD_TRANSFORM:
7584 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7585 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7586 VectorSet(tcmat + 6, 0 , 0 , 1);
7587 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7588 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7590 case Q3TCMOD_TURBULENT:
7591 // this is handled in the RSurf_PrepareVertices function
7592 matrix = identitymatrix;
7596 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7599 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7601 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7602 char name[MAX_QPATH];
7603 skinframe_t *skinframe;
7604 unsigned char pixels[296*194];
7605 strlcpy(cache->name, skinname, sizeof(cache->name));
7606 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7607 if (developer_loading.integer)
7608 Con_Printf("loading %s\n", name);
7609 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7610 if (!skinframe || !skinframe->base)
7613 fs_offset_t filesize;
7615 f = FS_LoadFile(name, tempmempool, true, &filesize);
7618 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7619 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7623 cache->skinframe = skinframe;
7626 texture_t *R_GetCurrentTexture(texture_t *t)
7629 const entity_render_t *ent = rsurface.entity;
7630 dp_model_t *model = ent->model;
7631 q3shaderinfo_layer_tcmod_t *tcmod;
7633 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7634 return t->currentframe;
7635 t->update_lastrenderframe = r_textureframe;
7636 t->update_lastrenderentity = (void *)ent;
7638 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7639 t->camera_entity = ent->entitynumber;
7641 t->camera_entity = 0;
7643 // switch to an alternate material if this is a q1bsp animated material
7645 texture_t *texture = t;
7646 int s = rsurface.ent_skinnum;
7647 if ((unsigned int)s >= (unsigned int)model->numskins)
7649 if (model->skinscenes)
7651 if (model->skinscenes[s].framecount > 1)
7652 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7654 s = model->skinscenes[s].firstframe;
7657 t = t + s * model->num_surfaces;
7660 // use an alternate animation if the entity's frame is not 0,
7661 // and only if the texture has an alternate animation
7662 if (rsurface.ent_alttextures && t->anim_total[1])
7663 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7665 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7667 texture->currentframe = t;
7670 // update currentskinframe to be a qw skin or animation frame
7671 if (rsurface.ent_qwskin >= 0)
7673 i = rsurface.ent_qwskin;
7674 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7676 r_qwskincache_size = cl.maxclients;
7678 Mem_Free(r_qwskincache);
7679 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7681 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7682 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7683 t->currentskinframe = r_qwskincache[i].skinframe;
7684 if (t->currentskinframe == NULL)
7685 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7687 else if (t->numskinframes >= 2)
7688 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7689 if (t->backgroundnumskinframes >= 2)
7690 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7692 t->currentmaterialflags = t->basematerialflags;
7693 t->currentalpha = rsurface.colormod[3];
7694 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7695 t->currentalpha *= r_wateralpha.value;
7696 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7697 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7698 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7699 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7700 if (!(rsurface.ent_flags & RENDER_LIGHT))
7701 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7702 else if (FAKELIGHT_ENABLED)
7704 // no modellight if using fakelight for the map
7706 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7708 // pick a model lighting mode
7709 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7710 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7712 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7714 if (rsurface.ent_flags & RENDER_ADDITIVE)
7715 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7716 else if (t->currentalpha < 1)
7717 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7718 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7719 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7720 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7721 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7722 if (t->backgroundnumskinframes)
7723 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7724 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7726 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7727 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7730 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7731 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7733 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7734 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7736 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7737 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7739 // there is no tcmod
7740 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7742 t->currenttexmatrix = r_waterscrollmatrix;
7743 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7745 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7747 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7748 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7751 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7752 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7753 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7754 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7756 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7757 if (t->currentskinframe->qpixels)
7758 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7759 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7760 if (!t->basetexture)
7761 t->basetexture = r_texture_notexture;
7762 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7763 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7764 t->nmaptexture = t->currentskinframe->nmap;
7765 if (!t->nmaptexture)
7766 t->nmaptexture = r_texture_blanknormalmap;
7767 t->glosstexture = r_texture_black;
7768 t->glowtexture = t->currentskinframe->glow;
7769 t->fogtexture = t->currentskinframe->fog;
7770 t->reflectmasktexture = t->currentskinframe->reflect;
7771 if (t->backgroundnumskinframes)
7773 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7774 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7775 t->backgroundglosstexture = r_texture_black;
7776 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7777 if (!t->backgroundnmaptexture)
7778 t->backgroundnmaptexture = r_texture_blanknormalmap;
7782 t->backgroundbasetexture = r_texture_white;
7783 t->backgroundnmaptexture = r_texture_blanknormalmap;
7784 t->backgroundglosstexture = r_texture_black;
7785 t->backgroundglowtexture = NULL;
7787 t->specularpower = r_shadow_glossexponent.value;
7788 // TODO: store reference values for these in the texture?
7789 t->specularscale = 0;
7790 if (r_shadow_gloss.integer > 0)
7792 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7794 if (r_shadow_glossintensity.value > 0)
7796 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7797 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7798 t->specularscale = r_shadow_glossintensity.value;
7801 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7803 t->glosstexture = r_texture_white;
7804 t->backgroundglosstexture = r_texture_white;
7805 t->specularscale = r_shadow_gloss2intensity.value;
7806 t->specularpower = r_shadow_gloss2exponent.value;
7809 t->specularscale *= t->specularscalemod;
7810 t->specularpower *= t->specularpowermod;
7812 // lightmaps mode looks bad with dlights using actual texturing, so turn
7813 // off the colormap and glossmap, but leave the normalmap on as it still
7814 // accurately represents the shading involved
7815 if (gl_lightmaps.integer)
7817 t->basetexture = r_texture_grey128;
7818 t->pantstexture = r_texture_black;
7819 t->shirttexture = r_texture_black;
7820 t->nmaptexture = r_texture_blanknormalmap;
7821 t->glosstexture = r_texture_black;
7822 t->glowtexture = NULL;
7823 t->fogtexture = NULL;
7824 t->reflectmasktexture = NULL;
7825 t->backgroundbasetexture = NULL;
7826 t->backgroundnmaptexture = r_texture_blanknormalmap;
7827 t->backgroundglosstexture = r_texture_black;
7828 t->backgroundglowtexture = NULL;
7829 t->specularscale = 0;
7830 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7833 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7834 VectorClear(t->dlightcolor);
7835 t->currentnumlayers = 0;
7836 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7838 int blendfunc1, blendfunc2;
7840 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7842 blendfunc1 = GL_SRC_ALPHA;
7843 blendfunc2 = GL_ONE;
7845 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7847 blendfunc1 = GL_SRC_ALPHA;
7848 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7850 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7852 blendfunc1 = t->customblendfunc[0];
7853 blendfunc2 = t->customblendfunc[1];
7857 blendfunc1 = GL_ONE;
7858 blendfunc2 = GL_ZERO;
7860 // don't colormod evilblend textures
7861 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7862 VectorSet(t->lightmapcolor, 1, 1, 1);
7863 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7864 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7866 // fullbright is not affected by r_refdef.lightmapintensity
7867 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]);
7868 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7869 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]);
7870 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7871 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]);
7875 vec3_t ambientcolor;
7877 // set the color tint used for lights affecting this surface
7878 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7880 // q3bsp has no lightmap updates, so the lightstylevalue that
7881 // would normally be baked into the lightmap must be
7882 // applied to the color
7883 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7884 if (model->type == mod_brushq3)
7885 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7886 colorscale *= r_refdef.lightmapintensity;
7887 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7888 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7889 // basic lit geometry
7890 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]);
7891 // add pants/shirt if needed
7892 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7893 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]);
7894 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7895 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]);
7896 // now add ambient passes if needed
7897 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7899 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]);
7900 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7901 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]);
7902 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7903 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]);
7906 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7907 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]);
7908 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7910 // if this is opaque use alpha blend which will darken the earlier
7913 // if this is an alpha blended material, all the earlier passes
7914 // were darkened by fog already, so we only need to add the fog
7915 // color ontop through the fog mask texture
7917 // if this is an additive blended material, all the earlier passes
7918 // were darkened by fog already, and we should not add fog color
7919 // (because the background was not darkened, there is no fog color
7920 // that was lost behind it).
7921 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]);
7925 return t->currentframe;
7928 rsurfacestate_t rsurface;
7930 void RSurf_ActiveWorldEntity(void)
7932 dp_model_t *model = r_refdef.scene.worldmodel;
7933 //if (rsurface.entity == r_refdef.scene.worldentity)
7935 rsurface.entity = r_refdef.scene.worldentity;
7936 rsurface.skeleton = NULL;
7937 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7938 rsurface.ent_skinnum = 0;
7939 rsurface.ent_qwskin = -1;
7940 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7941 rsurface.shadertime = r_refdef.scene.time;
7942 rsurface.matrix = identitymatrix;
7943 rsurface.inversematrix = identitymatrix;
7944 rsurface.matrixscale = 1;
7945 rsurface.inversematrixscale = 1;
7946 R_EntityMatrix(&identitymatrix);
7947 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7948 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7949 rsurface.fograngerecip = r_refdef.fograngerecip;
7950 rsurface.fogheightfade = r_refdef.fogheightfade;
7951 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7952 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7953 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7954 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7955 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7956 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7957 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7958 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7959 rsurface.colormod[3] = 1;
7960 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);
7961 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7962 rsurface.frameblend[0].lerp = 1;
7963 rsurface.ent_alttextures = false;
7964 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7965 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7966 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7967 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7968 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7969 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7970 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7971 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7972 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7973 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7974 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7975 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7976 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7977 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7978 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7979 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7980 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7981 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7982 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7983 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7984 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7985 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7986 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7987 rsurface.modelelement3i = model->surfmesh.data_element3i;
7988 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7989 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7990 rsurface.modelelement3s = model->surfmesh.data_element3s;
7991 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7992 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7993 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7994 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7995 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7996 rsurface.modelsurfaces = model->data_surfaces;
7997 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7998 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7999 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8000 rsurface.modelgeneratedvertex = false;
8001 rsurface.batchgeneratedvertex = false;
8002 rsurface.batchfirstvertex = 0;
8003 rsurface.batchnumvertices = 0;
8004 rsurface.batchfirsttriangle = 0;
8005 rsurface.batchnumtriangles = 0;
8006 rsurface.batchvertex3f = NULL;
8007 rsurface.batchvertex3f_vertexbuffer = NULL;
8008 rsurface.batchvertex3f_bufferoffset = 0;
8009 rsurface.batchsvector3f = NULL;
8010 rsurface.batchsvector3f_vertexbuffer = NULL;
8011 rsurface.batchsvector3f_bufferoffset = 0;
8012 rsurface.batchtvector3f = NULL;
8013 rsurface.batchtvector3f_vertexbuffer = NULL;
8014 rsurface.batchtvector3f_bufferoffset = 0;
8015 rsurface.batchnormal3f = NULL;
8016 rsurface.batchnormal3f_vertexbuffer = NULL;
8017 rsurface.batchnormal3f_bufferoffset = 0;
8018 rsurface.batchlightmapcolor4f = NULL;
8019 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8020 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8021 rsurface.batchtexcoordtexture2f = NULL;
8022 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8023 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8024 rsurface.batchtexcoordlightmap2f = NULL;
8025 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8026 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8027 rsurface.batchvertexmesh = NULL;
8028 rsurface.batchvertexmeshbuffer = NULL;
8029 rsurface.batchvertex3fbuffer = NULL;
8030 rsurface.batchelement3i = NULL;
8031 rsurface.batchelement3i_indexbuffer = NULL;
8032 rsurface.batchelement3i_bufferoffset = 0;
8033 rsurface.batchelement3s = NULL;
8034 rsurface.batchelement3s_indexbuffer = NULL;
8035 rsurface.batchelement3s_bufferoffset = 0;
8036 rsurface.passcolor4f = NULL;
8037 rsurface.passcolor4f_vertexbuffer = NULL;
8038 rsurface.passcolor4f_bufferoffset = 0;
8041 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8043 dp_model_t *model = ent->model;
8044 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8046 rsurface.entity = (entity_render_t *)ent;
8047 rsurface.skeleton = ent->skeleton;
8048 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8049 rsurface.ent_skinnum = ent->skinnum;
8050 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;
8051 rsurface.ent_flags = ent->flags;
8052 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8053 rsurface.matrix = ent->matrix;
8054 rsurface.inversematrix = ent->inversematrix;
8055 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8056 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8057 R_EntityMatrix(&rsurface.matrix);
8058 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8059 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8060 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8061 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8062 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8063 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8064 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8065 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8066 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8067 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8068 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8069 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8070 rsurface.colormod[3] = ent->alpha;
8071 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8072 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8073 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8074 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8075 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8076 if (ent->model->brush.submodel && !prepass)
8078 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8079 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8081 if (model->surfmesh.isanimated && model->AnimateVertices)
8083 if (ent->animcache_vertex3f)
8085 rsurface.modelvertex3f = ent->animcache_vertex3f;
8086 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8087 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8088 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8089 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8090 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8091 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8093 else if (wanttangents)
8095 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8096 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8097 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8098 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8099 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8100 rsurface.modelvertexmesh = NULL;
8101 rsurface.modelvertexmeshbuffer = NULL;
8102 rsurface.modelvertex3fbuffer = NULL;
8104 else if (wantnormals)
8106 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8107 rsurface.modelsvector3f = NULL;
8108 rsurface.modeltvector3f = NULL;
8109 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8110 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8111 rsurface.modelvertexmesh = NULL;
8112 rsurface.modelvertexmeshbuffer = NULL;
8113 rsurface.modelvertex3fbuffer = NULL;
8117 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8118 rsurface.modelsvector3f = NULL;
8119 rsurface.modeltvector3f = NULL;
8120 rsurface.modelnormal3f = NULL;
8121 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8122 rsurface.modelvertexmesh = NULL;
8123 rsurface.modelvertexmeshbuffer = NULL;
8124 rsurface.modelvertex3fbuffer = NULL;
8126 rsurface.modelvertex3f_vertexbuffer = 0;
8127 rsurface.modelvertex3f_bufferoffset = 0;
8128 rsurface.modelsvector3f_vertexbuffer = 0;
8129 rsurface.modelsvector3f_bufferoffset = 0;
8130 rsurface.modeltvector3f_vertexbuffer = 0;
8131 rsurface.modeltvector3f_bufferoffset = 0;
8132 rsurface.modelnormal3f_vertexbuffer = 0;
8133 rsurface.modelnormal3f_bufferoffset = 0;
8134 rsurface.modelgeneratedvertex = true;
8138 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8139 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8140 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8141 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8142 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8143 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8144 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8145 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8146 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8147 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8148 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8149 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8150 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8151 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8152 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8153 rsurface.modelgeneratedvertex = false;
8155 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8156 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8157 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8158 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8159 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8160 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8161 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8162 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8163 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8164 rsurface.modelelement3i = model->surfmesh.data_element3i;
8165 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8166 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8167 rsurface.modelelement3s = model->surfmesh.data_element3s;
8168 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8169 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8170 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8171 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8172 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8173 rsurface.modelsurfaces = model->data_surfaces;
8174 rsurface.batchgeneratedvertex = false;
8175 rsurface.batchfirstvertex = 0;
8176 rsurface.batchnumvertices = 0;
8177 rsurface.batchfirsttriangle = 0;
8178 rsurface.batchnumtriangles = 0;
8179 rsurface.batchvertex3f = NULL;
8180 rsurface.batchvertex3f_vertexbuffer = NULL;
8181 rsurface.batchvertex3f_bufferoffset = 0;
8182 rsurface.batchsvector3f = NULL;
8183 rsurface.batchsvector3f_vertexbuffer = NULL;
8184 rsurface.batchsvector3f_bufferoffset = 0;
8185 rsurface.batchtvector3f = NULL;
8186 rsurface.batchtvector3f_vertexbuffer = NULL;
8187 rsurface.batchtvector3f_bufferoffset = 0;
8188 rsurface.batchnormal3f = NULL;
8189 rsurface.batchnormal3f_vertexbuffer = NULL;
8190 rsurface.batchnormal3f_bufferoffset = 0;
8191 rsurface.batchlightmapcolor4f = NULL;
8192 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8193 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8194 rsurface.batchtexcoordtexture2f = NULL;
8195 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8196 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8197 rsurface.batchtexcoordlightmap2f = NULL;
8198 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8199 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8200 rsurface.batchvertexmesh = NULL;
8201 rsurface.batchvertexmeshbuffer = NULL;
8202 rsurface.batchvertex3fbuffer = NULL;
8203 rsurface.batchelement3i = NULL;
8204 rsurface.batchelement3i_indexbuffer = NULL;
8205 rsurface.batchelement3i_bufferoffset = 0;
8206 rsurface.batchelement3s = NULL;
8207 rsurface.batchelement3s_indexbuffer = NULL;
8208 rsurface.batchelement3s_bufferoffset = 0;
8209 rsurface.passcolor4f = NULL;
8210 rsurface.passcolor4f_vertexbuffer = NULL;
8211 rsurface.passcolor4f_bufferoffset = 0;
8214 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)
8216 rsurface.entity = r_refdef.scene.worldentity;
8217 rsurface.skeleton = NULL;
8218 rsurface.ent_skinnum = 0;
8219 rsurface.ent_qwskin = -1;
8220 rsurface.ent_flags = entflags;
8221 rsurface.shadertime = r_refdef.scene.time - shadertime;
8222 rsurface.modelnumvertices = numvertices;
8223 rsurface.modelnumtriangles = numtriangles;
8224 rsurface.matrix = *matrix;
8225 rsurface.inversematrix = *inversematrix;
8226 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8227 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8228 R_EntityMatrix(&rsurface.matrix);
8229 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8230 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8231 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8232 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8233 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8234 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8235 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8236 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8237 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8238 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8239 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8240 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8241 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);
8242 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8243 rsurface.frameblend[0].lerp = 1;
8244 rsurface.ent_alttextures = false;
8245 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8246 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8249 rsurface.modelvertex3f = (float *)vertex3f;
8250 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8251 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8252 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8254 else if (wantnormals)
8256 rsurface.modelvertex3f = (float *)vertex3f;
8257 rsurface.modelsvector3f = NULL;
8258 rsurface.modeltvector3f = NULL;
8259 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8263 rsurface.modelvertex3f = (float *)vertex3f;
8264 rsurface.modelsvector3f = NULL;
8265 rsurface.modeltvector3f = NULL;
8266 rsurface.modelnormal3f = NULL;
8268 rsurface.modelvertexmesh = NULL;
8269 rsurface.modelvertexmeshbuffer = NULL;
8270 rsurface.modelvertex3fbuffer = NULL;
8271 rsurface.modelvertex3f_vertexbuffer = 0;
8272 rsurface.modelvertex3f_bufferoffset = 0;
8273 rsurface.modelsvector3f_vertexbuffer = 0;
8274 rsurface.modelsvector3f_bufferoffset = 0;
8275 rsurface.modeltvector3f_vertexbuffer = 0;
8276 rsurface.modeltvector3f_bufferoffset = 0;
8277 rsurface.modelnormal3f_vertexbuffer = 0;
8278 rsurface.modelnormal3f_bufferoffset = 0;
8279 rsurface.modelgeneratedvertex = true;
8280 rsurface.modellightmapcolor4f = (float *)color4f;
8281 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8282 rsurface.modellightmapcolor4f_bufferoffset = 0;
8283 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8284 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8285 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8286 rsurface.modeltexcoordlightmap2f = NULL;
8287 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8288 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8289 rsurface.modelelement3i = (int *)element3i;
8290 rsurface.modelelement3i_indexbuffer = NULL;
8291 rsurface.modelelement3i_bufferoffset = 0;
8292 rsurface.modelelement3s = (unsigned short *)element3s;
8293 rsurface.modelelement3s_indexbuffer = NULL;
8294 rsurface.modelelement3s_bufferoffset = 0;
8295 rsurface.modellightmapoffsets = NULL;
8296 rsurface.modelsurfaces = NULL;
8297 rsurface.batchgeneratedvertex = false;
8298 rsurface.batchfirstvertex = 0;
8299 rsurface.batchnumvertices = 0;
8300 rsurface.batchfirsttriangle = 0;
8301 rsurface.batchnumtriangles = 0;
8302 rsurface.batchvertex3f = NULL;
8303 rsurface.batchvertex3f_vertexbuffer = NULL;
8304 rsurface.batchvertex3f_bufferoffset = 0;
8305 rsurface.batchsvector3f = NULL;
8306 rsurface.batchsvector3f_vertexbuffer = NULL;
8307 rsurface.batchsvector3f_bufferoffset = 0;
8308 rsurface.batchtvector3f = NULL;
8309 rsurface.batchtvector3f_vertexbuffer = NULL;
8310 rsurface.batchtvector3f_bufferoffset = 0;
8311 rsurface.batchnormal3f = NULL;
8312 rsurface.batchnormal3f_vertexbuffer = NULL;
8313 rsurface.batchnormal3f_bufferoffset = 0;
8314 rsurface.batchlightmapcolor4f = NULL;
8315 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8316 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8317 rsurface.batchtexcoordtexture2f = NULL;
8318 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8319 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8320 rsurface.batchtexcoordlightmap2f = NULL;
8321 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8322 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8323 rsurface.batchvertexmesh = NULL;
8324 rsurface.batchvertexmeshbuffer = NULL;
8325 rsurface.batchvertex3fbuffer = NULL;
8326 rsurface.batchelement3i = NULL;
8327 rsurface.batchelement3i_indexbuffer = NULL;
8328 rsurface.batchelement3i_bufferoffset = 0;
8329 rsurface.batchelement3s = NULL;
8330 rsurface.batchelement3s_indexbuffer = NULL;
8331 rsurface.batchelement3s_bufferoffset = 0;
8332 rsurface.passcolor4f = NULL;
8333 rsurface.passcolor4f_vertexbuffer = NULL;
8334 rsurface.passcolor4f_bufferoffset = 0;
8336 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8338 if ((wantnormals || wanttangents) && !normal3f)
8340 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8341 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8343 if (wanttangents && !svector3f)
8345 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8346 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8347 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8352 float RSurf_FogPoint(const float *v)
8354 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8355 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8356 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8357 float FogHeightFade = r_refdef.fogheightfade;
8359 unsigned int fogmasktableindex;
8360 if (r_refdef.fogplaneviewabove)
8361 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8363 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8364 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8365 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8368 float RSurf_FogVertex(const float *v)
8370 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8371 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8372 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8373 float FogHeightFade = rsurface.fogheightfade;
8375 unsigned int fogmasktableindex;
8376 if (r_refdef.fogplaneviewabove)
8377 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8379 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8380 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8381 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8384 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8387 for (i = 0;i < numelements;i++)
8388 outelement3i[i] = inelement3i[i] + adjust;
8391 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8392 extern cvar_t gl_vbo;
8393 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8401 int surfacefirsttriangle;
8402 int surfacenumtriangles;
8403 int surfacefirstvertex;
8404 int surfaceendvertex;
8405 int surfacenumvertices;
8406 int batchnumvertices;
8407 int batchnumtriangles;
8411 qboolean dynamicvertex;
8415 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8417 q3shaderinfo_deform_t *deform;
8418 const msurface_t *surface, *firstsurface;
8419 r_vertexmesh_t *vertexmesh;
8420 if (!texturenumsurfaces)
8422 // find vertex range of this surface batch
8424 firstsurface = texturesurfacelist[0];
8425 firsttriangle = firstsurface->num_firsttriangle;
8426 batchnumvertices = 0;
8427 batchnumtriangles = 0;
8428 firstvertex = endvertex = firstsurface->num_firstvertex;
8429 for (i = 0;i < texturenumsurfaces;i++)
8431 surface = texturesurfacelist[i];
8432 if (surface != firstsurface + i)
8434 surfacefirstvertex = surface->num_firstvertex;
8435 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8436 surfacenumvertices = surface->num_vertices;
8437 surfacenumtriangles = surface->num_triangles;
8438 if (firstvertex > surfacefirstvertex)
8439 firstvertex = surfacefirstvertex;
8440 if (endvertex < surfaceendvertex)
8441 endvertex = surfaceendvertex;
8442 batchnumvertices += surfacenumvertices;
8443 batchnumtriangles += surfacenumtriangles;
8446 // we now know the vertex range used, and if there are any gaps in it
8447 rsurface.batchfirstvertex = firstvertex;
8448 rsurface.batchnumvertices = endvertex - firstvertex;
8449 rsurface.batchfirsttriangle = firsttriangle;
8450 rsurface.batchnumtriangles = batchnumtriangles;
8452 // this variable holds flags for which properties have been updated that
8453 // may require regenerating vertexmesh array...
8456 // check if any dynamic vertex processing must occur
8457 dynamicvertex = false;
8459 // if there is a chance of animated vertex colors, it's a dynamic batch
8460 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8462 dynamicvertex = true;
8463 batchneed |= BATCHNEED_NOGAPS;
8464 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8467 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8469 switch (deform->deform)
8472 case Q3DEFORM_PROJECTIONSHADOW:
8473 case Q3DEFORM_TEXT0:
8474 case Q3DEFORM_TEXT1:
8475 case Q3DEFORM_TEXT2:
8476 case Q3DEFORM_TEXT3:
8477 case Q3DEFORM_TEXT4:
8478 case Q3DEFORM_TEXT5:
8479 case Q3DEFORM_TEXT6:
8480 case Q3DEFORM_TEXT7:
8483 case Q3DEFORM_AUTOSPRITE:
8484 dynamicvertex = true;
8485 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8486 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8488 case Q3DEFORM_AUTOSPRITE2:
8489 dynamicvertex = true;
8490 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8491 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8493 case Q3DEFORM_NORMAL:
8494 dynamicvertex = true;
8495 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8496 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8499 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8500 break; // if wavefunc is a nop, ignore this transform
8501 dynamicvertex = true;
8502 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8503 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8505 case Q3DEFORM_BULGE:
8506 dynamicvertex = true;
8507 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8508 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8511 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8512 break; // if wavefunc is a nop, ignore this transform
8513 dynamicvertex = true;
8514 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8515 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8519 switch(rsurface.texture->tcgen.tcgen)
8522 case Q3TCGEN_TEXTURE:
8524 case Q3TCGEN_LIGHTMAP:
8525 dynamicvertex = true;
8526 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8527 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8529 case Q3TCGEN_VECTOR:
8530 dynamicvertex = true;
8531 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8532 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8534 case Q3TCGEN_ENVIRONMENT:
8535 dynamicvertex = true;
8536 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8537 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8540 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8542 dynamicvertex = true;
8543 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8544 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8547 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8549 dynamicvertex = true;
8550 batchneed |= BATCHNEED_NOGAPS;
8551 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8554 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8556 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8557 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8558 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8559 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8560 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8561 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8562 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8565 // when the model data has no vertex buffer (dynamic mesh), we need to
8567 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8568 batchneed |= BATCHNEED_NOGAPS;
8570 // if needsupdate, we have to do a dynamic vertex batch for sure
8571 if (needsupdate & batchneed)
8572 dynamicvertex = true;
8574 // see if we need to build vertexmesh from arrays
8575 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8576 dynamicvertex = true;
8578 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8579 // also some drivers strongly dislike firstvertex
8580 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8581 dynamicvertex = true;
8583 rsurface.batchvertex3f = rsurface.modelvertex3f;
8584 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8585 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8586 rsurface.batchsvector3f = rsurface.modelsvector3f;
8587 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8588 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8589 rsurface.batchtvector3f = rsurface.modeltvector3f;
8590 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8591 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8592 rsurface.batchnormal3f = rsurface.modelnormal3f;
8593 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8594 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8595 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8596 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8597 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8598 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8599 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8600 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8601 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8602 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8603 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8604 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8605 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8606 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8607 rsurface.batchelement3i = rsurface.modelelement3i;
8608 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8609 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8610 rsurface.batchelement3s = rsurface.modelelement3s;
8611 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8612 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8614 // if any dynamic vertex processing has to occur in software, we copy the
8615 // entire surface list together before processing to rebase the vertices
8616 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8618 // if any gaps exist and we do not have a static vertex buffer, we have to
8619 // copy the surface list together to avoid wasting upload bandwidth on the
8620 // vertices in the gaps.
8622 // if gaps exist and we have a static vertex buffer, we still have to
8623 // combine the index buffer ranges into one dynamic index buffer.
8625 // in all cases we end up with data that can be drawn in one call.
8629 // static vertex data, just set pointers...
8630 rsurface.batchgeneratedvertex = false;
8631 // if there are gaps, we want to build a combined index buffer,
8632 // otherwise use the original static buffer with an appropriate offset
8635 // build a new triangle elements array for this batch
8636 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8637 rsurface.batchfirsttriangle = 0;
8639 for (i = 0;i < texturenumsurfaces;i++)
8641 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8642 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8643 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8644 numtriangles += surfacenumtriangles;
8646 rsurface.batchelement3i_indexbuffer = NULL;
8647 rsurface.batchelement3i_bufferoffset = 0;
8648 rsurface.batchelement3s = NULL;
8649 rsurface.batchelement3s_indexbuffer = NULL;
8650 rsurface.batchelement3s_bufferoffset = 0;
8651 if (endvertex <= 65536)
8653 // make a 16bit (unsigned short) index array if possible
8654 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8655 for (i = 0;i < numtriangles*3;i++)
8656 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8662 // something needs software processing, do it for real...
8663 // we only directly handle separate array data in this case and then
8664 // generate interleaved data if needed...
8665 rsurface.batchgeneratedvertex = true;
8667 // now copy the vertex data into a combined array and make an index array
8668 // (this is what Quake3 does all the time)
8669 //if (gaps || rsurface.batchfirstvertex)
8671 rsurface.batchvertex3fbuffer = NULL;
8672 rsurface.batchvertexmesh = NULL;
8673 rsurface.batchvertexmeshbuffer = NULL;
8674 rsurface.batchvertex3f = NULL;
8675 rsurface.batchvertex3f_vertexbuffer = NULL;
8676 rsurface.batchvertex3f_bufferoffset = 0;
8677 rsurface.batchsvector3f = NULL;
8678 rsurface.batchsvector3f_vertexbuffer = NULL;
8679 rsurface.batchsvector3f_bufferoffset = 0;
8680 rsurface.batchtvector3f = NULL;
8681 rsurface.batchtvector3f_vertexbuffer = NULL;
8682 rsurface.batchtvector3f_bufferoffset = 0;
8683 rsurface.batchnormal3f = NULL;
8684 rsurface.batchnormal3f_vertexbuffer = NULL;
8685 rsurface.batchnormal3f_bufferoffset = 0;
8686 rsurface.batchlightmapcolor4f = NULL;
8687 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8688 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8689 rsurface.batchtexcoordtexture2f = NULL;
8690 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8691 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8692 rsurface.batchtexcoordlightmap2f = NULL;
8693 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8694 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8695 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8696 rsurface.batchelement3i_indexbuffer = NULL;
8697 rsurface.batchelement3i_bufferoffset = 0;
8698 rsurface.batchelement3s = NULL;
8699 rsurface.batchelement3s_indexbuffer = NULL;
8700 rsurface.batchelement3s_bufferoffset = 0;
8701 // we'll only be setting up certain arrays as needed
8702 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8703 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8704 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8705 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8706 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8707 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8708 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8710 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8711 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8713 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8714 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8715 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8716 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8717 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8718 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8721 for (i = 0;i < texturenumsurfaces;i++)
8723 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8724 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8725 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8726 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8727 // copy only the data requested
8728 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8729 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8730 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8732 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8734 if (rsurface.batchvertex3f)
8735 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8737 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8739 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8741 if (rsurface.modelnormal3f)
8742 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8744 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8746 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8748 if (rsurface.modelsvector3f)
8750 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8751 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8755 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8756 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8759 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8761 if (rsurface.modellightmapcolor4f)
8762 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8764 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8766 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8768 if (rsurface.modeltexcoordtexture2f)
8769 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8771 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8773 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8775 if (rsurface.modeltexcoordlightmap2f)
8776 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8778 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8781 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8782 numvertices += surfacenumvertices;
8783 numtriangles += surfacenumtriangles;
8786 // generate a 16bit index array as well if possible
8787 // (in general, dynamic batches fit)
8788 if (numvertices <= 65536)
8790 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8791 for (i = 0;i < numtriangles*3;i++)
8792 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8795 // since we've copied everything, the batch now starts at 0
8796 rsurface.batchfirstvertex = 0;
8797 rsurface.batchnumvertices = batchnumvertices;
8798 rsurface.batchfirsttriangle = 0;
8799 rsurface.batchnumtriangles = batchnumtriangles;
8802 // q1bsp surfaces rendered in vertex color mode have to have colors
8803 // calculated based on lightstyles
8804 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8806 // generate color arrays for the surfaces in this list
8811 const unsigned char *lm;
8812 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8813 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8814 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8816 for (i = 0;i < texturenumsurfaces;i++)
8818 surface = texturesurfacelist[i];
8819 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8820 surfacenumvertices = surface->num_vertices;
8821 if (surface->lightmapinfo->samples)
8823 for (j = 0;j < surfacenumvertices;j++)
8825 lm = surface->lightmapinfo->samples + offsets[j];
8826 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8827 VectorScale(lm, scale, c);
8828 if (surface->lightmapinfo->styles[1] != 255)
8830 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8832 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8833 VectorMA(c, scale, lm, c);
8834 if (surface->lightmapinfo->styles[2] != 255)
8837 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8838 VectorMA(c, scale, lm, c);
8839 if (surface->lightmapinfo->styles[3] != 255)
8842 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8843 VectorMA(c, scale, lm, c);
8850 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);
8856 for (j = 0;j < surfacenumvertices;j++)
8858 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8865 // if vertices are deformed (sprite flares and things in maps, possibly
8866 // water waves, bulges and other deformations), modify the copied vertices
8868 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8870 switch (deform->deform)
8873 case Q3DEFORM_PROJECTIONSHADOW:
8874 case Q3DEFORM_TEXT0:
8875 case Q3DEFORM_TEXT1:
8876 case Q3DEFORM_TEXT2:
8877 case Q3DEFORM_TEXT3:
8878 case Q3DEFORM_TEXT4:
8879 case Q3DEFORM_TEXT5:
8880 case Q3DEFORM_TEXT6:
8881 case Q3DEFORM_TEXT7:
8884 case Q3DEFORM_AUTOSPRITE:
8885 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8886 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8887 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8888 VectorNormalize(newforward);
8889 VectorNormalize(newright);
8890 VectorNormalize(newup);
8891 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8892 // rsurface.batchvertex3f_vertexbuffer = NULL;
8893 // rsurface.batchvertex3f_bufferoffset = 0;
8894 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8895 // rsurface.batchsvector3f_vertexbuffer = NULL;
8896 // rsurface.batchsvector3f_bufferoffset = 0;
8897 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8898 // rsurface.batchtvector3f_vertexbuffer = NULL;
8899 // rsurface.batchtvector3f_bufferoffset = 0;
8900 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8901 // rsurface.batchnormal3f_vertexbuffer = NULL;
8902 // rsurface.batchnormal3f_bufferoffset = 0;
8903 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8904 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8905 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8906 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8907 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);
8908 // a single autosprite surface can contain multiple sprites...
8909 for (j = 0;j < batchnumvertices - 3;j += 4)
8911 VectorClear(center);
8912 for (i = 0;i < 4;i++)
8913 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8914 VectorScale(center, 0.25f, center);
8915 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8916 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8917 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8918 for (i = 0;i < 4;i++)
8920 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8921 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8924 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8925 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8926 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);
8928 case Q3DEFORM_AUTOSPRITE2:
8929 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8930 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8931 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8932 VectorNormalize(newforward);
8933 VectorNormalize(newright);
8934 VectorNormalize(newup);
8935 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8936 // rsurface.batchvertex3f_vertexbuffer = NULL;
8937 // rsurface.batchvertex3f_bufferoffset = 0;
8939 const float *v1, *v2;
8949 memset(shortest, 0, sizeof(shortest));
8950 // a single autosprite surface can contain multiple sprites...
8951 for (j = 0;j < batchnumvertices - 3;j += 4)
8953 VectorClear(center);
8954 for (i = 0;i < 4;i++)
8955 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8956 VectorScale(center, 0.25f, center);
8957 // find the two shortest edges, then use them to define the
8958 // axis vectors for rotating around the central axis
8959 for (i = 0;i < 6;i++)
8961 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8962 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8963 l = VectorDistance2(v1, v2);
8964 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8966 l += (1.0f / 1024.0f);
8967 if (shortest[0].length2 > l || i == 0)
8969 shortest[1] = shortest[0];
8970 shortest[0].length2 = l;
8971 shortest[0].v1 = v1;
8972 shortest[0].v2 = v2;
8974 else if (shortest[1].length2 > l || i == 1)
8976 shortest[1].length2 = l;
8977 shortest[1].v1 = v1;
8978 shortest[1].v2 = v2;
8981 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8982 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8983 // this calculates the right vector from the shortest edge
8984 // and the up vector from the edge midpoints
8985 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8986 VectorNormalize(right);
8987 VectorSubtract(end, start, up);
8988 VectorNormalize(up);
8989 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8990 VectorSubtract(rsurface.localvieworigin, center, forward);
8991 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8992 VectorNegate(forward, forward);
8993 VectorReflect(forward, 0, up, forward);
8994 VectorNormalize(forward);
8995 CrossProduct(up, forward, newright);
8996 VectorNormalize(newright);
8997 // rotate the quad around the up axis vector, this is made
8998 // especially easy by the fact we know the quad is flat,
8999 // so we only have to subtract the center position and
9000 // measure distance along the right vector, and then
9001 // multiply that by the newright vector and add back the
9003 // we also need to subtract the old position to undo the
9004 // displacement from the center, which we do with a
9005 // DotProduct, the subtraction/addition of center is also
9006 // optimized into DotProducts here
9007 l = DotProduct(right, center);
9008 for (i = 0;i < 4;i++)
9010 v1 = rsurface.batchvertex3f + 3*(j+i);
9011 f = DotProduct(right, v1) - l;
9012 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9016 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9018 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9019 // rsurface.batchnormal3f_vertexbuffer = NULL;
9020 // rsurface.batchnormal3f_bufferoffset = 0;
9021 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9023 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9025 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9026 // rsurface.batchsvector3f_vertexbuffer = NULL;
9027 // rsurface.batchsvector3f_bufferoffset = 0;
9028 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9029 // rsurface.batchtvector3f_vertexbuffer = NULL;
9030 // rsurface.batchtvector3f_bufferoffset = 0;
9031 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);
9034 case Q3DEFORM_NORMAL:
9035 // deform the normals to make reflections wavey
9036 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9037 rsurface.batchnormal3f_vertexbuffer = NULL;
9038 rsurface.batchnormal3f_bufferoffset = 0;
9039 for (j = 0;j < batchnumvertices;j++)
9042 float *normal = rsurface.batchnormal3f + 3*j;
9043 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9044 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9045 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9046 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9047 VectorNormalize(normal);
9049 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9051 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9052 // rsurface.batchsvector3f_vertexbuffer = NULL;
9053 // rsurface.batchsvector3f_bufferoffset = 0;
9054 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9055 // rsurface.batchtvector3f_vertexbuffer = NULL;
9056 // rsurface.batchtvector3f_bufferoffset = 0;
9057 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);
9061 // deform vertex array to make wavey water and flags and such
9062 waveparms[0] = deform->waveparms[0];
9063 waveparms[1] = deform->waveparms[1];
9064 waveparms[2] = deform->waveparms[2];
9065 waveparms[3] = deform->waveparms[3];
9066 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9067 break; // if wavefunc is a nop, don't make a dynamic vertex array
9068 // this is how a divisor of vertex influence on deformation
9069 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9070 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9071 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9072 // rsurface.batchvertex3f_vertexbuffer = NULL;
9073 // rsurface.batchvertex3f_bufferoffset = 0;
9074 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9075 // rsurface.batchnormal3f_vertexbuffer = NULL;
9076 // rsurface.batchnormal3f_bufferoffset = 0;
9077 for (j = 0;j < batchnumvertices;j++)
9079 // if the wavefunc depends on time, evaluate it per-vertex
9082 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9083 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9085 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9087 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9088 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9089 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9091 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9092 // rsurface.batchsvector3f_vertexbuffer = NULL;
9093 // rsurface.batchsvector3f_bufferoffset = 0;
9094 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9095 // rsurface.batchtvector3f_vertexbuffer = NULL;
9096 // rsurface.batchtvector3f_bufferoffset = 0;
9097 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);
9100 case Q3DEFORM_BULGE:
9101 // deform vertex array to make the surface have moving bulges
9102 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9103 // rsurface.batchvertex3f_vertexbuffer = NULL;
9104 // rsurface.batchvertex3f_bufferoffset = 0;
9105 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9106 // rsurface.batchnormal3f_vertexbuffer = NULL;
9107 // rsurface.batchnormal3f_bufferoffset = 0;
9108 for (j = 0;j < batchnumvertices;j++)
9110 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9111 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9113 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9114 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9115 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9117 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9118 // rsurface.batchsvector3f_vertexbuffer = NULL;
9119 // rsurface.batchsvector3f_bufferoffset = 0;
9120 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9121 // rsurface.batchtvector3f_vertexbuffer = NULL;
9122 // rsurface.batchtvector3f_bufferoffset = 0;
9123 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);
9127 // deform vertex array
9128 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9129 break; // if wavefunc is a nop, don't make a dynamic vertex array
9130 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9131 VectorScale(deform->parms, scale, waveparms);
9132 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9133 // rsurface.batchvertex3f_vertexbuffer = NULL;
9134 // rsurface.batchvertex3f_bufferoffset = 0;
9135 for (j = 0;j < batchnumvertices;j++)
9136 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9141 // generate texcoords based on the chosen texcoord source
9142 switch(rsurface.texture->tcgen.tcgen)
9145 case Q3TCGEN_TEXTURE:
9147 case Q3TCGEN_LIGHTMAP:
9148 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9149 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9150 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9151 if (rsurface.batchtexcoordlightmap2f)
9152 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9154 case Q3TCGEN_VECTOR:
9155 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9156 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9157 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9158 for (j = 0;j < batchnumvertices;j++)
9160 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9161 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9164 case Q3TCGEN_ENVIRONMENT:
9165 // make environment reflections using a spheremap
9166 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9167 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9168 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9169 for (j = 0;j < batchnumvertices;j++)
9171 // identical to Q3A's method, but executed in worldspace so
9172 // carried models can be shiny too
9174 float viewer[3], d, reflected[3], worldreflected[3];
9176 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9177 // VectorNormalize(viewer);
9179 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9181 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9182 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9183 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9184 // note: this is proportinal to viewer, so we can normalize later
9186 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9187 VectorNormalize(worldreflected);
9189 // note: this sphere map only uses world x and z!
9190 // so positive and negative y will LOOK THE SAME.
9191 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9192 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9196 // the only tcmod that needs software vertex processing is turbulent, so
9197 // check for it here and apply the changes if needed
9198 // and we only support that as the first one
9199 // (handling a mixture of turbulent and other tcmods would be problematic
9200 // without punting it entirely to a software path)
9201 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9203 amplitude = rsurface.texture->tcmods[0].parms[1];
9204 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9205 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9206 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9207 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9208 for (j = 0;j < batchnumvertices;j++)
9210 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);
9211 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9215 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9217 // convert the modified arrays to vertex structs
9218 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9219 // rsurface.batchvertexmeshbuffer = NULL;
9220 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9221 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9222 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9223 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9224 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9225 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9226 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9228 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9230 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9231 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9234 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9235 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9236 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9237 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9238 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9239 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9240 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9241 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9242 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9246 void RSurf_DrawBatch(void)
9248 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9249 // through the pipeline, killing it earlier in the pipeline would have
9250 // per-surface overhead rather than per-batch overhead, so it's best to
9251 // reject it here, before it hits glDraw.
9252 if (rsurface.batchnumtriangles == 0)
9255 // batch debugging code
9256 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9262 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9263 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9266 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9268 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9270 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9271 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);
9278 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);
9281 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9283 // pick the closest matching water plane
9284 int planeindex, vertexindex, bestplaneindex = -1;
9288 r_waterstate_waterplane_t *p;
9289 qboolean prepared = false;
9291 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9293 if(p->camera_entity != rsurface.texture->camera_entity)
9298 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9300 if(rsurface.batchnumvertices == 0)
9303 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9305 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9306 d += fabs(PlaneDiff(vert, &p->plane));
9308 if (bestd > d || bestplaneindex < 0)
9311 bestplaneindex = planeindex;
9314 return bestplaneindex;
9315 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9316 // this situation though, as it might be better to render single larger
9317 // batches with useless stuff (backface culled for example) than to
9318 // render multiple smaller batches
9321 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9324 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9325 rsurface.passcolor4f_vertexbuffer = 0;
9326 rsurface.passcolor4f_bufferoffset = 0;
9327 for (i = 0;i < rsurface.batchnumvertices;i++)
9328 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9331 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9338 if (rsurface.passcolor4f)
9340 // generate color arrays
9341 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9342 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9343 rsurface.passcolor4f_vertexbuffer = 0;
9344 rsurface.passcolor4f_bufferoffset = 0;
9345 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)
9347 f = RSurf_FogVertex(v);
9356 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9357 rsurface.passcolor4f_vertexbuffer = 0;
9358 rsurface.passcolor4f_bufferoffset = 0;
9359 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9361 f = RSurf_FogVertex(v);
9370 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9377 if (!rsurface.passcolor4f)
9379 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9380 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9381 rsurface.passcolor4f_vertexbuffer = 0;
9382 rsurface.passcolor4f_bufferoffset = 0;
9383 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)
9385 f = RSurf_FogVertex(v);
9386 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9387 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9388 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9393 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9398 if (!rsurface.passcolor4f)
9400 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9401 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9402 rsurface.passcolor4f_vertexbuffer = 0;
9403 rsurface.passcolor4f_bufferoffset = 0;
9404 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9413 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9418 if (!rsurface.passcolor4f)
9420 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9421 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9422 rsurface.passcolor4f_vertexbuffer = 0;
9423 rsurface.passcolor4f_bufferoffset = 0;
9424 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9426 c2[0] = c[0] + r_refdef.scene.ambient;
9427 c2[1] = c[1] + r_refdef.scene.ambient;
9428 c2[2] = c[2] + r_refdef.scene.ambient;
9433 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9436 rsurface.passcolor4f = NULL;
9437 rsurface.passcolor4f_vertexbuffer = 0;
9438 rsurface.passcolor4f_bufferoffset = 0;
9439 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9440 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9441 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9442 GL_Color(r, g, b, a);
9443 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9447 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9449 // TODO: optimize applyfog && applycolor case
9450 // just apply fog if necessary, and tint the fog color array if necessary
9451 rsurface.passcolor4f = NULL;
9452 rsurface.passcolor4f_vertexbuffer = 0;
9453 rsurface.passcolor4f_bufferoffset = 0;
9454 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9455 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9456 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9457 GL_Color(r, g, b, a);
9461 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9464 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9465 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9466 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9467 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9468 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9469 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9470 GL_Color(r, g, b, a);
9474 static void RSurf_DrawBatch_GL11_ClampColor(void)
9479 if (!rsurface.passcolor4f)
9481 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9483 c2[0] = bound(0.0f, c1[0], 1.0f);
9484 c2[1] = bound(0.0f, c1[1], 1.0f);
9485 c2[2] = bound(0.0f, c1[2], 1.0f);
9486 c2[3] = bound(0.0f, c1[3], 1.0f);
9490 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9500 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9501 rsurface.passcolor4f_vertexbuffer = 0;
9502 rsurface.passcolor4f_bufferoffset = 0;
9503 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)
9505 f = -DotProduct(r_refdef.view.forward, n);
9507 f = f * 0.85 + 0.15; // work around so stuff won't get black
9508 f *= r_refdef.lightmapintensity;
9509 Vector4Set(c, f, f, f, 1);
9513 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9515 RSurf_DrawBatch_GL11_ApplyFakeLight();
9516 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9517 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9518 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9519 GL_Color(r, g, b, a);
9523 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9531 vec3_t ambientcolor;
9532 vec3_t diffusecolor;
9536 VectorCopy(rsurface.modellight_lightdir, lightdir);
9537 f = 0.5f * r_refdef.lightmapintensity;
9538 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9539 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9540 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9541 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9542 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9543 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9545 if (VectorLength2(diffusecolor) > 0)
9547 // q3-style directional shading
9548 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9549 rsurface.passcolor4f_vertexbuffer = 0;
9550 rsurface.passcolor4f_bufferoffset = 0;
9551 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)
9553 if ((f = DotProduct(n, lightdir)) > 0)
9554 VectorMA(ambientcolor, f, diffusecolor, c);
9556 VectorCopy(ambientcolor, c);
9563 *applycolor = false;
9567 *r = ambientcolor[0];
9568 *g = ambientcolor[1];
9569 *b = ambientcolor[2];
9570 rsurface.passcolor4f = NULL;
9571 rsurface.passcolor4f_vertexbuffer = 0;
9572 rsurface.passcolor4f_bufferoffset = 0;
9576 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9578 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9579 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9580 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9581 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9582 GL_Color(r, g, b, a);
9586 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9594 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9595 rsurface.passcolor4f_vertexbuffer = 0;
9596 rsurface.passcolor4f_bufferoffset = 0;
9598 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9600 f = 1 - RSurf_FogVertex(v);
9608 void RSurf_SetupDepthAndCulling(void)
9610 // submodels are biased to avoid z-fighting with world surfaces that they
9611 // may be exactly overlapping (avoids z-fighting artifacts on certain
9612 // doors and things in Quake maps)
9613 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9614 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9615 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9616 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9619 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9621 // transparent sky would be ridiculous
9622 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9624 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9625 skyrenderlater = true;
9626 RSurf_SetupDepthAndCulling();
9628 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9629 // skymasking on them, and Quake3 never did sky masking (unlike
9630 // software Quake and software Quake2), so disable the sky masking
9631 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9632 // and skymasking also looks very bad when noclipping outside the
9633 // level, so don't use it then either.
9634 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9636 R_Mesh_ResetTextureState();
9637 if (skyrendermasked)
9639 R_SetupShader_DepthOrShadow(false);
9640 // depth-only (masking)
9641 GL_ColorMask(0,0,0,0);
9642 // just to make sure that braindead drivers don't draw
9643 // anything despite that colormask...
9644 GL_BlendFunc(GL_ZERO, GL_ONE);
9645 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9646 if (rsurface.batchvertex3fbuffer)
9647 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9649 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9653 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9655 GL_BlendFunc(GL_ONE, GL_ZERO);
9656 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9657 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9658 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9661 if (skyrendermasked)
9662 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9664 R_Mesh_ResetTextureState();
9665 GL_Color(1, 1, 1, 1);
9668 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9669 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9670 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9672 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9676 // render screenspace normalmap to texture
9678 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9682 // bind lightmap texture
9684 // water/refraction/reflection/camera surfaces have to be handled specially
9685 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9687 int start, end, startplaneindex;
9688 for (start = 0;start < texturenumsurfaces;start = end)
9690 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9691 if(startplaneindex < 0)
9693 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9694 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9698 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9700 // now that we have a batch using the same planeindex, render it
9701 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9703 // render water or distortion background
9705 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);
9707 // blend surface on top
9708 GL_DepthMask(false);
9709 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9712 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9714 // render surface with reflection texture as input
9715 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9716 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);
9723 // render surface batch normally
9724 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9725 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);
9729 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9731 // OpenGL 1.3 path - anything not completely ancient
9732 qboolean applycolor;
9735 const texturelayer_t *layer;
9736 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);
9737 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9739 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9742 int layertexrgbscale;
9743 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9745 if (layerindex == 0)
9749 GL_AlphaTest(false);
9750 GL_DepthFunc(GL_EQUAL);
9753 GL_DepthMask(layer->depthmask && writedepth);
9754 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9755 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9757 layertexrgbscale = 4;
9758 VectorScale(layer->color, 0.25f, layercolor);
9760 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9762 layertexrgbscale = 2;
9763 VectorScale(layer->color, 0.5f, layercolor);
9767 layertexrgbscale = 1;
9768 VectorScale(layer->color, 1.0f, layercolor);
9770 layercolor[3] = layer->color[3];
9771 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9772 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9773 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9774 switch (layer->type)
9776 case TEXTURELAYERTYPE_LITTEXTURE:
9777 // single-pass lightmapped texture with 2x rgbscale
9778 R_Mesh_TexBind(0, r_texture_white);
9779 R_Mesh_TexMatrix(0, NULL);
9780 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9781 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9782 R_Mesh_TexBind(1, layer->texture);
9783 R_Mesh_TexMatrix(1, &layer->texmatrix);
9784 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9785 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9786 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9787 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9788 else if (FAKELIGHT_ENABLED)
9789 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9790 else if (rsurface.uselightmaptexture)
9791 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9793 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9795 case TEXTURELAYERTYPE_TEXTURE:
9796 // singletexture unlit texture with transparency support
9797 R_Mesh_TexBind(0, layer->texture);
9798 R_Mesh_TexMatrix(0, &layer->texmatrix);
9799 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9800 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9801 R_Mesh_TexBind(1, 0);
9802 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9803 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9805 case TEXTURELAYERTYPE_FOG:
9806 // singletexture fogging
9809 R_Mesh_TexBind(0, layer->texture);
9810 R_Mesh_TexMatrix(0, &layer->texmatrix);
9811 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9812 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9816 R_Mesh_TexBind(0, 0);
9817 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9819 R_Mesh_TexBind(1, 0);
9820 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9821 // generate a color array for the fog pass
9822 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9823 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9827 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9830 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9832 GL_DepthFunc(GL_LEQUAL);
9833 GL_AlphaTest(false);
9837 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9839 // OpenGL 1.1 - crusty old voodoo path
9842 const texturelayer_t *layer;
9843 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);
9844 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9846 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9848 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9850 if (layerindex == 0)
9854 GL_AlphaTest(false);
9855 GL_DepthFunc(GL_EQUAL);
9858 GL_DepthMask(layer->depthmask && writedepth);
9859 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9860 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9861 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9862 switch (layer->type)
9864 case TEXTURELAYERTYPE_LITTEXTURE:
9865 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9867 // two-pass lit texture with 2x rgbscale
9868 // first the lightmap pass
9869 R_Mesh_TexBind(0, r_texture_white);
9870 R_Mesh_TexMatrix(0, NULL);
9871 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9872 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9873 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9874 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9875 else if (FAKELIGHT_ENABLED)
9876 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9877 else if (rsurface.uselightmaptexture)
9878 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9880 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9881 // then apply the texture to it
9882 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9883 R_Mesh_TexBind(0, layer->texture);
9884 R_Mesh_TexMatrix(0, &layer->texmatrix);
9885 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9886 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9887 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);
9891 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9892 R_Mesh_TexBind(0, layer->texture);
9893 R_Mesh_TexMatrix(0, &layer->texmatrix);
9894 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9895 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9896 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9897 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);
9899 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);
9902 case TEXTURELAYERTYPE_TEXTURE:
9903 // singletexture unlit texture with transparency support
9904 R_Mesh_TexBind(0, layer->texture);
9905 R_Mesh_TexMatrix(0, &layer->texmatrix);
9906 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9907 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9908 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);
9910 case TEXTURELAYERTYPE_FOG:
9911 // singletexture fogging
9914 R_Mesh_TexBind(0, layer->texture);
9915 R_Mesh_TexMatrix(0, &layer->texmatrix);
9916 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9917 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9921 R_Mesh_TexBind(0, 0);
9922 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9924 // generate a color array for the fog pass
9925 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9926 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9930 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9933 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9935 GL_DepthFunc(GL_LEQUAL);
9936 GL_AlphaTest(false);
9940 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9944 r_vertexgeneric_t *batchvertex;
9947 // R_Mesh_ResetTextureState();
9948 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9950 if(rsurface.texture && rsurface.texture->currentskinframe)
9952 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9953 c[3] *= rsurface.texture->currentalpha;
9963 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9965 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9966 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9967 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9970 // brighten it up (as texture value 127 means "unlit")
9971 c[0] *= 2 * r_refdef.view.colorscale;
9972 c[1] *= 2 * r_refdef.view.colorscale;
9973 c[2] *= 2 * r_refdef.view.colorscale;
9975 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9976 c[3] *= r_wateralpha.value;
9978 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9980 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9981 GL_DepthMask(false);
9983 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9985 GL_BlendFunc(GL_ONE, GL_ONE);
9986 GL_DepthMask(false);
9988 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9990 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9991 GL_DepthMask(false);
9993 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9995 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9996 GL_DepthMask(false);
10000 GL_BlendFunc(GL_ONE, GL_ZERO);
10001 GL_DepthMask(writedepth);
10004 if (r_showsurfaces.integer == 3)
10006 rsurface.passcolor4f = NULL;
10008 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10010 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10012 rsurface.passcolor4f = NULL;
10013 rsurface.passcolor4f_vertexbuffer = 0;
10014 rsurface.passcolor4f_bufferoffset = 0;
10016 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10018 qboolean applycolor = true;
10021 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10023 r_refdef.lightmapintensity = 1;
10024 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10025 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10027 else if (FAKELIGHT_ENABLED)
10029 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10031 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10032 RSurf_DrawBatch_GL11_ApplyFakeLight();
10033 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10037 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10039 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10040 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10041 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10044 if(!rsurface.passcolor4f)
10045 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10047 RSurf_DrawBatch_GL11_ApplyAmbient();
10048 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10049 if(r_refdef.fogenabled)
10050 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10051 RSurf_DrawBatch_GL11_ClampColor();
10053 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10054 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10057 else if (!r_refdef.view.showdebug)
10059 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10060 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10061 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10063 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10064 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10066 R_Mesh_PrepareVertices_Generic_Unlock();
10069 else if (r_showsurfaces.integer == 4)
10071 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10072 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10073 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10075 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10076 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10077 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10079 R_Mesh_PrepareVertices_Generic_Unlock();
10082 else if (r_showsurfaces.integer == 2)
10085 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10086 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10087 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10089 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10090 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10091 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10092 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10093 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10094 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10095 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10097 R_Mesh_PrepareVertices_Generic_Unlock();
10098 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10102 int texturesurfaceindex;
10104 const msurface_t *surface;
10105 float surfacecolor4f[4];
10106 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10107 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10109 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10111 surface = texturesurfacelist[texturesurfaceindex];
10112 k = (int)(((size_t)surface) / sizeof(msurface_t));
10113 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10114 for (j = 0;j < surface->num_vertices;j++)
10116 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10117 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10121 R_Mesh_PrepareVertices_Generic_Unlock();
10126 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10129 RSurf_SetupDepthAndCulling();
10130 if (r_showsurfaces.integer)
10132 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10135 switch (vid.renderpath)
10137 case RENDERPATH_GL20:
10138 case RENDERPATH_D3D9:
10139 case RENDERPATH_D3D10:
10140 case RENDERPATH_D3D11:
10141 case RENDERPATH_SOFT:
10142 case RENDERPATH_GLES2:
10143 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10145 case RENDERPATH_GL13:
10146 case RENDERPATH_GLES1:
10147 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10149 case RENDERPATH_GL11:
10150 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10156 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10159 RSurf_SetupDepthAndCulling();
10160 if (r_showsurfaces.integer)
10162 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10165 switch (vid.renderpath)
10167 case RENDERPATH_GL20:
10168 case RENDERPATH_D3D9:
10169 case RENDERPATH_D3D10:
10170 case RENDERPATH_D3D11:
10171 case RENDERPATH_SOFT:
10172 case RENDERPATH_GLES2:
10173 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10175 case RENDERPATH_GL13:
10176 case RENDERPATH_GLES1:
10177 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10179 case RENDERPATH_GL11:
10180 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10186 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10189 int texturenumsurfaces, endsurface;
10190 texture_t *texture;
10191 const msurface_t *surface;
10192 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10194 // if the model is static it doesn't matter what value we give for
10195 // wantnormals and wanttangents, so this logic uses only rules applicable
10196 // to a model, knowing that they are meaningless otherwise
10197 if (ent == r_refdef.scene.worldentity)
10198 RSurf_ActiveWorldEntity();
10199 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10200 RSurf_ActiveModelEntity(ent, false, false, false);
10203 switch (vid.renderpath)
10205 case RENDERPATH_GL20:
10206 case RENDERPATH_D3D9:
10207 case RENDERPATH_D3D10:
10208 case RENDERPATH_D3D11:
10209 case RENDERPATH_SOFT:
10210 case RENDERPATH_GLES2:
10211 RSurf_ActiveModelEntity(ent, true, true, false);
10213 case RENDERPATH_GL11:
10214 case RENDERPATH_GL13:
10215 case RENDERPATH_GLES1:
10216 RSurf_ActiveModelEntity(ent, true, false, false);
10221 if (r_transparentdepthmasking.integer)
10223 qboolean setup = false;
10224 for (i = 0;i < numsurfaces;i = j)
10227 surface = rsurface.modelsurfaces + surfacelist[i];
10228 texture = surface->texture;
10229 rsurface.texture = R_GetCurrentTexture(texture);
10230 rsurface.lightmaptexture = NULL;
10231 rsurface.deluxemaptexture = NULL;
10232 rsurface.uselightmaptexture = false;
10233 // scan ahead until we find a different texture
10234 endsurface = min(i + 1024, numsurfaces);
10235 texturenumsurfaces = 0;
10236 texturesurfacelist[texturenumsurfaces++] = surface;
10237 for (;j < endsurface;j++)
10239 surface = rsurface.modelsurfaces + surfacelist[j];
10240 if (texture != surface->texture)
10242 texturesurfacelist[texturenumsurfaces++] = surface;
10244 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10246 // render the range of surfaces as depth
10250 GL_ColorMask(0,0,0,0);
10252 GL_DepthTest(true);
10253 GL_BlendFunc(GL_ONE, GL_ZERO);
10254 GL_DepthMask(true);
10255 // R_Mesh_ResetTextureState();
10256 R_SetupShader_DepthOrShadow(false);
10258 RSurf_SetupDepthAndCulling();
10259 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10260 if (rsurface.batchvertex3fbuffer)
10261 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10263 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10267 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10270 for (i = 0;i < numsurfaces;i = j)
10273 surface = rsurface.modelsurfaces + surfacelist[i];
10274 texture = surface->texture;
10275 rsurface.texture = R_GetCurrentTexture(texture);
10276 // scan ahead until we find a different texture
10277 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10278 texturenumsurfaces = 0;
10279 texturesurfacelist[texturenumsurfaces++] = surface;
10280 if(FAKELIGHT_ENABLED)
10282 rsurface.lightmaptexture = NULL;
10283 rsurface.deluxemaptexture = NULL;
10284 rsurface.uselightmaptexture = false;
10285 for (;j < endsurface;j++)
10287 surface = rsurface.modelsurfaces + surfacelist[j];
10288 if (texture != surface->texture)
10290 texturesurfacelist[texturenumsurfaces++] = surface;
10295 rsurface.lightmaptexture = surface->lightmaptexture;
10296 rsurface.deluxemaptexture = surface->deluxemaptexture;
10297 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10298 for (;j < endsurface;j++)
10300 surface = rsurface.modelsurfaces + surfacelist[j];
10301 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10303 texturesurfacelist[texturenumsurfaces++] = surface;
10306 // render the range of surfaces
10307 if (ent == r_refdef.scene.worldentity)
10308 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10310 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10312 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10315 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10317 // transparent surfaces get pushed off into the transparent queue
10318 int surfacelistindex;
10319 const msurface_t *surface;
10320 vec3_t tempcenter, center;
10321 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10323 surface = texturesurfacelist[surfacelistindex];
10324 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10325 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10326 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10327 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10328 if (queueentity->transparent_offset) // transparent offset
10330 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10331 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10332 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10334 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10338 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10340 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10342 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10344 RSurf_SetupDepthAndCulling();
10345 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10346 if (rsurface.batchvertex3fbuffer)
10347 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10349 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10353 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10355 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10358 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10361 if (!rsurface.texture->currentnumlayers)
10363 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10364 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10366 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10368 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10369 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10370 else if (!rsurface.texture->currentnumlayers)
10372 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10374 // in the deferred case, transparent surfaces were queued during prepass
10375 if (!r_shadow_usingdeferredprepass)
10376 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10380 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10381 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10386 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10389 texture_t *texture;
10390 R_FrameData_SetMark();
10391 // break the surface list down into batches by texture and use of lightmapping
10392 for (i = 0;i < numsurfaces;i = j)
10395 // texture is the base texture pointer, rsurface.texture is the
10396 // current frame/skin the texture is directing us to use (for example
10397 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10398 // use skin 1 instead)
10399 texture = surfacelist[i]->texture;
10400 rsurface.texture = R_GetCurrentTexture(texture);
10401 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10403 // if this texture is not the kind we want, skip ahead to the next one
10404 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10408 if(FAKELIGHT_ENABLED || depthonly || prepass)
10410 rsurface.lightmaptexture = NULL;
10411 rsurface.deluxemaptexture = NULL;
10412 rsurface.uselightmaptexture = false;
10413 // simply scan ahead until we find a different texture or lightmap state
10414 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10419 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10420 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10421 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10422 // simply scan ahead until we find a different texture or lightmap state
10423 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10426 // render the range of surfaces
10427 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10429 R_FrameData_ReturnToMark();
10432 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10436 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10439 if (!rsurface.texture->currentnumlayers)
10441 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10442 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10444 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10446 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10447 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10448 else if (!rsurface.texture->currentnumlayers)
10450 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10452 // in the deferred case, transparent surfaces were queued during prepass
10453 if (!r_shadow_usingdeferredprepass)
10454 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10458 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10459 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10464 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10467 texture_t *texture;
10468 R_FrameData_SetMark();
10469 // break the surface list down into batches by texture and use of lightmapping
10470 for (i = 0;i < numsurfaces;i = j)
10473 // texture is the base texture pointer, rsurface.texture is the
10474 // current frame/skin the texture is directing us to use (for example
10475 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10476 // use skin 1 instead)
10477 texture = surfacelist[i]->texture;
10478 rsurface.texture = R_GetCurrentTexture(texture);
10479 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10481 // if this texture is not the kind we want, skip ahead to the next one
10482 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10486 if(FAKELIGHT_ENABLED || depthonly || prepass)
10488 rsurface.lightmaptexture = NULL;
10489 rsurface.deluxemaptexture = NULL;
10490 rsurface.uselightmaptexture = false;
10491 // simply scan ahead until we find a different texture or lightmap state
10492 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10497 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10498 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10499 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10500 // simply scan ahead until we find a different texture or lightmap state
10501 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10504 // render the range of surfaces
10505 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10507 R_FrameData_ReturnToMark();
10510 float locboxvertex3f[6*4*3] =
10512 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10513 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10514 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10515 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10516 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10517 1,0,0, 0,0,0, 0,1,0, 1,1,0
10520 unsigned short locboxelements[6*2*3] =
10525 12,13,14, 12,14,15,
10526 16,17,18, 16,18,19,
10530 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10533 cl_locnode_t *loc = (cl_locnode_t *)ent;
10535 float vertex3f[6*4*3];
10537 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10538 GL_DepthMask(false);
10539 GL_DepthRange(0, 1);
10540 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10541 GL_DepthTest(true);
10542 GL_CullFace(GL_NONE);
10543 R_EntityMatrix(&identitymatrix);
10545 // R_Mesh_ResetTextureState();
10547 i = surfacelist[0];
10548 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10549 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10550 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10551 surfacelist[0] < 0 ? 0.5f : 0.125f);
10553 if (VectorCompare(loc->mins, loc->maxs))
10555 VectorSet(size, 2, 2, 2);
10556 VectorMA(loc->mins, -0.5f, size, mins);
10560 VectorCopy(loc->mins, mins);
10561 VectorSubtract(loc->maxs, loc->mins, size);
10564 for (i = 0;i < 6*4*3;)
10565 for (j = 0;j < 3;j++, i++)
10566 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10568 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10569 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10570 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10573 void R_DrawLocs(void)
10576 cl_locnode_t *loc, *nearestloc;
10578 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10579 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10581 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10582 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10586 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10588 if (decalsystem->decals)
10589 Mem_Free(decalsystem->decals);
10590 memset(decalsystem, 0, sizeof(*decalsystem));
10593 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)
10596 tridecal_t *decals;
10599 // expand or initialize the system
10600 if (decalsystem->maxdecals <= decalsystem->numdecals)
10602 decalsystem_t old = *decalsystem;
10603 qboolean useshortelements;
10604 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10605 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10606 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)));
10607 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10608 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10609 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10610 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10611 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10612 if (decalsystem->numdecals)
10613 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10615 Mem_Free(old.decals);
10616 for (i = 0;i < decalsystem->maxdecals*3;i++)
10617 decalsystem->element3i[i] = i;
10618 if (useshortelements)
10619 for (i = 0;i < decalsystem->maxdecals*3;i++)
10620 decalsystem->element3s[i] = i;
10623 // grab a decal and search for another free slot for the next one
10624 decals = decalsystem->decals;
10625 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10626 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10628 decalsystem->freedecal = i;
10629 if (decalsystem->numdecals <= i)
10630 decalsystem->numdecals = i + 1;
10632 // initialize the decal
10634 decal->triangleindex = triangleindex;
10635 decal->surfaceindex = surfaceindex;
10636 decal->decalsequence = decalsequence;
10637 decal->color4f[0][0] = c0[0];
10638 decal->color4f[0][1] = c0[1];
10639 decal->color4f[0][2] = c0[2];
10640 decal->color4f[0][3] = 1;
10641 decal->color4f[1][0] = c1[0];
10642 decal->color4f[1][1] = c1[1];
10643 decal->color4f[1][2] = c1[2];
10644 decal->color4f[1][3] = 1;
10645 decal->color4f[2][0] = c2[0];
10646 decal->color4f[2][1] = c2[1];
10647 decal->color4f[2][2] = c2[2];
10648 decal->color4f[2][3] = 1;
10649 decal->vertex3f[0][0] = v0[0];
10650 decal->vertex3f[0][1] = v0[1];
10651 decal->vertex3f[0][2] = v0[2];
10652 decal->vertex3f[1][0] = v1[0];
10653 decal->vertex3f[1][1] = v1[1];
10654 decal->vertex3f[1][2] = v1[2];
10655 decal->vertex3f[2][0] = v2[0];
10656 decal->vertex3f[2][1] = v2[1];
10657 decal->vertex3f[2][2] = v2[2];
10658 decal->texcoord2f[0][0] = t0[0];
10659 decal->texcoord2f[0][1] = t0[1];
10660 decal->texcoord2f[1][0] = t1[0];
10661 decal->texcoord2f[1][1] = t1[1];
10662 decal->texcoord2f[2][0] = t2[0];
10663 decal->texcoord2f[2][1] = t2[1];
10664 TriangleNormal(v0, v1, v2, decal->plane);
10665 VectorNormalize(decal->plane);
10666 decal->plane[3] = DotProduct(v0, decal->plane);
10669 extern cvar_t cl_decals_bias;
10670 extern cvar_t cl_decals_models;
10671 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10672 // baseparms, parms, temps
10673 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)
10678 const float *vertex3f;
10679 const float *normal3f;
10681 float points[2][9][3];
10688 e = rsurface.modelelement3i + 3*triangleindex;
10690 vertex3f = rsurface.modelvertex3f;
10691 normal3f = rsurface.modelnormal3f;
10695 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10697 index = 3*e[cornerindex];
10698 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10703 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10705 index = 3*e[cornerindex];
10706 VectorCopy(vertex3f + index, v[cornerindex]);
10711 //TriangleNormal(v[0], v[1], v[2], normal);
10712 //if (DotProduct(normal, localnormal) < 0.0f)
10714 // clip by each of the box planes formed from the projection matrix
10715 // if anything survives, we emit the decal
10716 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]);
10719 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]);
10722 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]);
10725 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]);
10728 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]);
10731 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]);
10734 // some part of the triangle survived, so we have to accept it...
10737 // dynamic always uses the original triangle
10739 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10741 index = 3*e[cornerindex];
10742 VectorCopy(vertex3f + index, v[cornerindex]);
10745 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10747 // convert vertex positions to texcoords
10748 Matrix4x4_Transform(projection, v[cornerindex], temp);
10749 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10750 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10751 // calculate distance fade from the projection origin
10752 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10753 f = bound(0.0f, f, 1.0f);
10754 c[cornerindex][0] = r * f;
10755 c[cornerindex][1] = g * f;
10756 c[cornerindex][2] = b * f;
10757 c[cornerindex][3] = 1.0f;
10758 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10761 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);
10763 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10764 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);
10766 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)
10768 matrix4x4_t projection;
10769 decalsystem_t *decalsystem;
10772 const msurface_t *surface;
10773 const msurface_t *surfaces;
10774 const int *surfacelist;
10775 const texture_t *texture;
10777 int numsurfacelist;
10778 int surfacelistindex;
10781 float localorigin[3];
10782 float localnormal[3];
10783 float localmins[3];
10784 float localmaxs[3];
10787 float planes[6][4];
10790 int bih_triangles_count;
10791 int bih_triangles[256];
10792 int bih_surfaces[256];
10794 decalsystem = &ent->decalsystem;
10795 model = ent->model;
10796 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10798 R_DecalSystem_Reset(&ent->decalsystem);
10802 if (!model->brush.data_leafs && !cl_decals_models.integer)
10804 if (decalsystem->model)
10805 R_DecalSystem_Reset(decalsystem);
10809 if (decalsystem->model != model)
10810 R_DecalSystem_Reset(decalsystem);
10811 decalsystem->model = model;
10813 RSurf_ActiveModelEntity(ent, true, false, false);
10815 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10816 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10817 VectorNormalize(localnormal);
10818 localsize = worldsize*rsurface.inversematrixscale;
10819 localmins[0] = localorigin[0] - localsize;
10820 localmins[1] = localorigin[1] - localsize;
10821 localmins[2] = localorigin[2] - localsize;
10822 localmaxs[0] = localorigin[0] + localsize;
10823 localmaxs[1] = localorigin[1] + localsize;
10824 localmaxs[2] = localorigin[2] + localsize;
10826 //VectorCopy(localnormal, planes[4]);
10827 //VectorVectors(planes[4], planes[2], planes[0]);
10828 AnglesFromVectors(angles, localnormal, NULL, false);
10829 AngleVectors(angles, planes[0], planes[2], planes[4]);
10830 VectorNegate(planes[0], planes[1]);
10831 VectorNegate(planes[2], planes[3]);
10832 VectorNegate(planes[4], planes[5]);
10833 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10834 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10835 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10836 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10837 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10838 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10843 matrix4x4_t forwardprojection;
10844 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10845 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10850 float projectionvector[4][3];
10851 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10852 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10853 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10854 projectionvector[0][0] = planes[0][0] * ilocalsize;
10855 projectionvector[0][1] = planes[1][0] * ilocalsize;
10856 projectionvector[0][2] = planes[2][0] * ilocalsize;
10857 projectionvector[1][0] = planes[0][1] * ilocalsize;
10858 projectionvector[1][1] = planes[1][1] * ilocalsize;
10859 projectionvector[1][2] = planes[2][1] * ilocalsize;
10860 projectionvector[2][0] = planes[0][2] * ilocalsize;
10861 projectionvector[2][1] = planes[1][2] * ilocalsize;
10862 projectionvector[2][2] = planes[2][2] * ilocalsize;
10863 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10864 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10865 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10866 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10870 dynamic = model->surfmesh.isanimated;
10871 numsurfacelist = model->nummodelsurfaces;
10872 surfacelist = model->sortedmodelsurfaces;
10873 surfaces = model->data_surfaces;
10876 bih_triangles_count = -1;
10879 if(model->render_bih.numleafs)
10880 bih = &model->render_bih;
10881 else if(model->collision_bih.numleafs)
10882 bih = &model->collision_bih;
10885 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10886 if(bih_triangles_count == 0)
10888 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10890 if(bih_triangles_count > 0)
10892 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10894 surfaceindex = bih_surfaces[triangleindex];
10895 surface = surfaces + surfaceindex;
10896 texture = surface->texture;
10897 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10899 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10901 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10906 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10908 surfaceindex = surfacelist[surfacelistindex];
10909 surface = surfaces + surfaceindex;
10910 // check cull box first because it rejects more than any other check
10911 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10913 // skip transparent surfaces
10914 texture = surface->texture;
10915 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10917 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10919 numtriangles = surface->num_triangles;
10920 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10921 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10926 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10927 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)
10929 int renderentityindex;
10930 float worldmins[3];
10931 float worldmaxs[3];
10932 entity_render_t *ent;
10934 if (!cl_decals_newsystem.integer)
10937 worldmins[0] = worldorigin[0] - worldsize;
10938 worldmins[1] = worldorigin[1] - worldsize;
10939 worldmins[2] = worldorigin[2] - worldsize;
10940 worldmaxs[0] = worldorigin[0] + worldsize;
10941 worldmaxs[1] = worldorigin[1] + worldsize;
10942 worldmaxs[2] = worldorigin[2] + worldsize;
10944 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10946 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10948 ent = r_refdef.scene.entities[renderentityindex];
10949 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10952 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10956 typedef struct r_decalsystem_splatqueue_s
10958 vec3_t worldorigin;
10959 vec3_t worldnormal;
10965 r_decalsystem_splatqueue_t;
10967 int r_decalsystem_numqueued = 0;
10968 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10970 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)
10972 r_decalsystem_splatqueue_t *queue;
10974 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10977 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10978 VectorCopy(worldorigin, queue->worldorigin);
10979 VectorCopy(worldnormal, queue->worldnormal);
10980 Vector4Set(queue->color, r, g, b, a);
10981 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10982 queue->worldsize = worldsize;
10983 queue->decalsequence = cl.decalsequence++;
10986 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10989 r_decalsystem_splatqueue_t *queue;
10991 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10992 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);
10993 r_decalsystem_numqueued = 0;
10996 extern cvar_t cl_decals_max;
10997 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11000 decalsystem_t *decalsystem = &ent->decalsystem;
11007 if (!decalsystem->numdecals)
11010 if (r_showsurfaces.integer)
11013 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11015 R_DecalSystem_Reset(decalsystem);
11019 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11020 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11022 if (decalsystem->lastupdatetime)
11023 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11026 decalsystem->lastupdatetime = r_refdef.scene.time;
11027 decal = decalsystem->decals;
11028 numdecals = decalsystem->numdecals;
11030 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11032 if (decal->color4f[0][3])
11034 decal->lived += frametime;
11035 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11037 memset(decal, 0, sizeof(*decal));
11038 if (decalsystem->freedecal > i)
11039 decalsystem->freedecal = i;
11043 decal = decalsystem->decals;
11044 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11047 // collapse the array by shuffling the tail decals into the gaps
11050 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11051 decalsystem->freedecal++;
11052 if (decalsystem->freedecal == numdecals)
11054 decal[decalsystem->freedecal] = decal[--numdecals];
11057 decalsystem->numdecals = numdecals;
11059 if (numdecals <= 0)
11061 // if there are no decals left, reset decalsystem
11062 R_DecalSystem_Reset(decalsystem);
11066 extern skinframe_t *decalskinframe;
11067 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11070 decalsystem_t *decalsystem = &ent->decalsystem;
11079 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11082 numdecals = decalsystem->numdecals;
11086 if (r_showsurfaces.integer)
11089 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11091 R_DecalSystem_Reset(decalsystem);
11095 // if the model is static it doesn't matter what value we give for
11096 // wantnormals and wanttangents, so this logic uses only rules applicable
11097 // to a model, knowing that they are meaningless otherwise
11098 if (ent == r_refdef.scene.worldentity)
11099 RSurf_ActiveWorldEntity();
11101 RSurf_ActiveModelEntity(ent, false, false, false);
11103 decalsystem->lastupdatetime = r_refdef.scene.time;
11104 decal = decalsystem->decals;
11106 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11108 // update vertex positions for animated models
11109 v3f = decalsystem->vertex3f;
11110 c4f = decalsystem->color4f;
11111 t2f = decalsystem->texcoord2f;
11112 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11114 if (!decal->color4f[0][3])
11117 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11121 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11124 // update color values for fading decals
11125 if (decal->lived >= cl_decals_time.value)
11126 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11130 c4f[ 0] = decal->color4f[0][0] * alpha;
11131 c4f[ 1] = decal->color4f[0][1] * alpha;
11132 c4f[ 2] = decal->color4f[0][2] * alpha;
11134 c4f[ 4] = decal->color4f[1][0] * alpha;
11135 c4f[ 5] = decal->color4f[1][1] * alpha;
11136 c4f[ 6] = decal->color4f[1][2] * alpha;
11138 c4f[ 8] = decal->color4f[2][0] * alpha;
11139 c4f[ 9] = decal->color4f[2][1] * alpha;
11140 c4f[10] = decal->color4f[2][2] * alpha;
11143 t2f[0] = decal->texcoord2f[0][0];
11144 t2f[1] = decal->texcoord2f[0][1];
11145 t2f[2] = decal->texcoord2f[1][0];
11146 t2f[3] = decal->texcoord2f[1][1];
11147 t2f[4] = decal->texcoord2f[2][0];
11148 t2f[5] = decal->texcoord2f[2][1];
11150 // update vertex positions for animated models
11151 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11153 e = rsurface.modelelement3i + 3*decal->triangleindex;
11154 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11155 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11156 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11160 VectorCopy(decal->vertex3f[0], v3f);
11161 VectorCopy(decal->vertex3f[1], v3f + 3);
11162 VectorCopy(decal->vertex3f[2], v3f + 6);
11165 if (r_refdef.fogenabled)
11167 alpha = RSurf_FogVertex(v3f);
11168 VectorScale(c4f, alpha, c4f);
11169 alpha = RSurf_FogVertex(v3f + 3);
11170 VectorScale(c4f + 4, alpha, c4f + 4);
11171 alpha = RSurf_FogVertex(v3f + 6);
11172 VectorScale(c4f + 8, alpha, c4f + 8);
11183 r_refdef.stats.drawndecals += numtris;
11185 // now render the decals all at once
11186 // (this assumes they all use one particle font texture!)
11187 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);
11188 // R_Mesh_ResetTextureState();
11189 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11190 GL_DepthMask(false);
11191 GL_DepthRange(0, 1);
11192 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11193 GL_DepthTest(true);
11194 GL_CullFace(GL_NONE);
11195 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11196 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11197 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11201 static void R_DrawModelDecals(void)
11205 // fade faster when there are too many decals
11206 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11207 for (i = 0;i < r_refdef.scene.numentities;i++)
11208 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11210 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11211 for (i = 0;i < r_refdef.scene.numentities;i++)
11212 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11213 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11215 R_DecalSystem_ApplySplatEntitiesQueue();
11217 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11218 for (i = 0;i < r_refdef.scene.numentities;i++)
11219 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11221 r_refdef.stats.totaldecals += numdecals;
11223 if (r_showsurfaces.integer)
11226 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11228 for (i = 0;i < r_refdef.scene.numentities;i++)
11230 if (!r_refdef.viewcache.entityvisible[i])
11232 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11233 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11237 extern cvar_t mod_collision_bih;
11238 void R_DrawDebugModel(void)
11240 entity_render_t *ent = rsurface.entity;
11241 int i, j, k, l, flagsmask;
11242 const msurface_t *surface;
11243 dp_model_t *model = ent->model;
11246 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11249 if (r_showoverdraw.value > 0)
11251 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11252 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11253 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11254 GL_DepthTest(false);
11255 GL_DepthMask(false);
11256 GL_DepthRange(0, 1);
11257 GL_BlendFunc(GL_ONE, GL_ONE);
11258 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11260 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11262 rsurface.texture = R_GetCurrentTexture(surface->texture);
11263 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11265 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11266 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11267 if (!rsurface.texture->currentlayers->depthmask)
11268 GL_Color(c, 0, 0, 1.0f);
11269 else if (ent == r_refdef.scene.worldentity)
11270 GL_Color(c, c, c, 1.0f);
11272 GL_Color(0, c, 0, 1.0f);
11273 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11277 rsurface.texture = NULL;
11280 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11282 // R_Mesh_ResetTextureState();
11283 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11284 GL_DepthRange(0, 1);
11285 GL_DepthTest(!r_showdisabledepthtest.integer);
11286 GL_DepthMask(false);
11287 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11289 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11293 qboolean cullbox = ent == r_refdef.scene.worldentity;
11294 const q3mbrush_t *brush;
11295 const bih_t *bih = &model->collision_bih;
11296 const bih_leaf_t *bihleaf;
11297 float vertex3f[3][3];
11298 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11300 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11302 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11304 switch (bihleaf->type)
11307 brush = model->brush.data_brushes + bihleaf->itemindex;
11308 if (brush->colbrushf && brush->colbrushf->numtriangles)
11310 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);
11311 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11312 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11315 case BIH_COLLISIONTRIANGLE:
11316 triangleindex = bihleaf->itemindex;
11317 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11318 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11319 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11320 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);
11321 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11322 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11324 case BIH_RENDERTRIANGLE:
11325 triangleindex = bihleaf->itemindex;
11326 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11327 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11328 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11329 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);
11330 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11331 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11337 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11339 if (r_showtris.integer && qglPolygonMode)
11341 if (r_showdisabledepthtest.integer)
11343 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11344 GL_DepthMask(false);
11348 GL_BlendFunc(GL_ONE, GL_ZERO);
11349 GL_DepthMask(true);
11351 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11352 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11354 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11356 rsurface.texture = R_GetCurrentTexture(surface->texture);
11357 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11359 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11360 if (!rsurface.texture->currentlayers->depthmask)
11361 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11362 else if (ent == r_refdef.scene.worldentity)
11363 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11365 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11366 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11370 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11371 rsurface.texture = NULL;
11374 if (r_shownormals.value != 0 && qglBegin)
11376 if (r_showdisabledepthtest.integer)
11378 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11379 GL_DepthMask(false);
11383 GL_BlendFunc(GL_ONE, GL_ZERO);
11384 GL_DepthMask(true);
11386 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11388 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11390 rsurface.texture = R_GetCurrentTexture(surface->texture);
11391 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11393 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11394 qglBegin(GL_LINES);
11395 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11397 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11399 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11400 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11401 qglVertex3f(v[0], v[1], v[2]);
11402 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11403 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11404 qglVertex3f(v[0], v[1], v[2]);
11407 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11409 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11411 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11412 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11413 qglVertex3f(v[0], v[1], v[2]);
11414 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11415 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11416 qglVertex3f(v[0], v[1], v[2]);
11419 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11421 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11423 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11424 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11425 qglVertex3f(v[0], v[1], v[2]);
11426 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11427 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11428 qglVertex3f(v[0], v[1], v[2]);
11431 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11433 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11435 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11436 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11437 qglVertex3f(v[0], v[1], v[2]);
11438 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11439 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11440 qglVertex3f(v[0], v[1], v[2]);
11447 rsurface.texture = NULL;
11451 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11452 int r_maxsurfacelist = 0;
11453 const msurface_t **r_surfacelist = NULL;
11454 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11456 int i, j, endj, flagsmask;
11457 dp_model_t *model = r_refdef.scene.worldmodel;
11458 msurface_t *surfaces;
11459 unsigned char *update;
11460 int numsurfacelist = 0;
11464 if (r_maxsurfacelist < model->num_surfaces)
11466 r_maxsurfacelist = model->num_surfaces;
11468 Mem_Free((msurface_t**)r_surfacelist);
11469 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11472 RSurf_ActiveWorldEntity();
11474 surfaces = model->data_surfaces;
11475 update = model->brushq1.lightmapupdateflags;
11477 // update light styles on this submodel
11478 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11480 model_brush_lightstyleinfo_t *style;
11481 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11483 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11485 int *list = style->surfacelist;
11486 style->value = r_refdef.scene.lightstylevalue[style->style];
11487 for (j = 0;j < style->numsurfaces;j++)
11488 update[list[j]] = true;
11493 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11497 R_DrawDebugModel();
11498 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11502 rsurface.lightmaptexture = NULL;
11503 rsurface.deluxemaptexture = NULL;
11504 rsurface.uselightmaptexture = false;
11505 rsurface.texture = NULL;
11506 rsurface.rtlight = NULL;
11507 numsurfacelist = 0;
11508 // add visible surfaces to draw list
11509 for (i = 0;i < model->nummodelsurfaces;i++)
11511 j = model->sortedmodelsurfaces[i];
11512 if (r_refdef.viewcache.world_surfacevisible[j])
11513 r_surfacelist[numsurfacelist++] = surfaces + j;
11515 // update lightmaps if needed
11516 if (model->brushq1.firstrender)
11518 model->brushq1.firstrender = false;
11519 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11521 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11525 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11526 if (r_refdef.viewcache.world_surfacevisible[j])
11528 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11530 // don't do anything if there were no surfaces
11531 if (!numsurfacelist)
11533 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11536 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11538 // add to stats if desired
11539 if (r_speeds.integer && !skysurfaces && !depthonly)
11541 r_refdef.stats.world_surfaces += numsurfacelist;
11542 for (j = 0;j < numsurfacelist;j++)
11543 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11546 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11549 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11551 int i, j, endj, flagsmask;
11552 dp_model_t *model = ent->model;
11553 msurface_t *surfaces;
11554 unsigned char *update;
11555 int numsurfacelist = 0;
11559 if (r_maxsurfacelist < model->num_surfaces)
11561 r_maxsurfacelist = model->num_surfaces;
11563 Mem_Free((msurface_t **)r_surfacelist);
11564 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11567 // if the model is static it doesn't matter what value we give for
11568 // wantnormals and wanttangents, so this logic uses only rules applicable
11569 // to a model, knowing that they are meaningless otherwise
11570 if (ent == r_refdef.scene.worldentity)
11571 RSurf_ActiveWorldEntity();
11572 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11573 RSurf_ActiveModelEntity(ent, false, false, false);
11575 RSurf_ActiveModelEntity(ent, true, true, true);
11576 else if (depthonly)
11578 switch (vid.renderpath)
11580 case RENDERPATH_GL20:
11581 case RENDERPATH_D3D9:
11582 case RENDERPATH_D3D10:
11583 case RENDERPATH_D3D11:
11584 case RENDERPATH_SOFT:
11585 case RENDERPATH_GLES2:
11586 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11588 case RENDERPATH_GL11:
11589 case RENDERPATH_GL13:
11590 case RENDERPATH_GLES1:
11591 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11597 switch (vid.renderpath)
11599 case RENDERPATH_GL20:
11600 case RENDERPATH_D3D9:
11601 case RENDERPATH_D3D10:
11602 case RENDERPATH_D3D11:
11603 case RENDERPATH_SOFT:
11604 case RENDERPATH_GLES2:
11605 RSurf_ActiveModelEntity(ent, true, true, false);
11607 case RENDERPATH_GL11:
11608 case RENDERPATH_GL13:
11609 case RENDERPATH_GLES1:
11610 RSurf_ActiveModelEntity(ent, true, false, false);
11615 surfaces = model->data_surfaces;
11616 update = model->brushq1.lightmapupdateflags;
11618 // update light styles
11619 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11621 model_brush_lightstyleinfo_t *style;
11622 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11624 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11626 int *list = style->surfacelist;
11627 style->value = r_refdef.scene.lightstylevalue[style->style];
11628 for (j = 0;j < style->numsurfaces;j++)
11629 update[list[j]] = true;
11634 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11638 R_DrawDebugModel();
11639 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11643 rsurface.lightmaptexture = NULL;
11644 rsurface.deluxemaptexture = NULL;
11645 rsurface.uselightmaptexture = false;
11646 rsurface.texture = NULL;
11647 rsurface.rtlight = NULL;
11648 numsurfacelist = 0;
11649 // add visible surfaces to draw list
11650 for (i = 0;i < model->nummodelsurfaces;i++)
11651 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11652 // don't do anything if there were no surfaces
11653 if (!numsurfacelist)
11655 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11658 // update lightmaps if needed
11662 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11667 R_BuildLightMap(ent, surfaces + j);
11672 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11674 R_BuildLightMap(ent, surfaces + j);
11675 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11677 // add to stats if desired
11678 if (r_speeds.integer && !skysurfaces && !depthonly)
11680 r_refdef.stats.entities_surfaces += numsurfacelist;
11681 for (j = 0;j < numsurfacelist;j++)
11682 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11685 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11688 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11690 static texture_t texture;
11691 static msurface_t surface;
11692 const msurface_t *surfacelist = &surface;
11694 // fake enough texture and surface state to render this geometry
11696 texture.update_lastrenderframe = -1; // regenerate this texture
11697 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11698 texture.currentskinframe = skinframe;
11699 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11700 texture.offsetmapping = OFFSETMAPPING_OFF;
11701 texture.offsetscale = 1;
11702 texture.specularscalemod = 1;
11703 texture.specularpowermod = 1;
11705 surface.texture = &texture;
11706 surface.num_triangles = numtriangles;
11707 surface.num_firsttriangle = firsttriangle;
11708 surface.num_vertices = numvertices;
11709 surface.num_firstvertex = firstvertex;
11712 rsurface.texture = R_GetCurrentTexture(surface.texture);
11713 rsurface.lightmaptexture = NULL;
11714 rsurface.deluxemaptexture = NULL;
11715 rsurface.uselightmaptexture = false;
11716 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11719 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)
11721 static msurface_t surface;
11722 const msurface_t *surfacelist = &surface;
11724 // fake enough texture and surface state to render this geometry
11725 surface.texture = texture;
11726 surface.num_triangles = numtriangles;
11727 surface.num_firsttriangle = firsttriangle;
11728 surface.num_vertices = numvertices;
11729 surface.num_firstvertex = firstvertex;
11732 rsurface.texture = R_GetCurrentTexture(surface.texture);
11733 rsurface.lightmaptexture = NULL;
11734 rsurface.deluxemaptexture = NULL;
11735 rsurface.uselightmaptexture = false;
11736 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);