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;
47 static qboolean r_gpuskeletal;
54 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
55 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 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)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 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"};
61 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"};
62 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"};
63 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"};
64 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"};
65 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"};
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 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"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 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)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
73 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"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 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"};
81 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
82 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
85 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)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 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"};
89 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"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 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)"};
102 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)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 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."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 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."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 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"};
127 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"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 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"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
138 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
149 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)"};
150 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"};
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
156 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
157 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"};
158 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"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 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"};
162 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)"};
163 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)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 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)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 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)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 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)"};
172 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)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
175 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183 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)"};
184 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)"};
186 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)"};
187 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
188 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"};
189 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
190 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
191 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
192 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"};
193 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
194 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
196 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
197 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
198 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
199 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
201 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
202 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
204 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
205 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
206 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
207 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
208 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
209 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
211 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
212 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
213 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
214 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
215 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
218 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
219 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
220 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
222 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"};
224 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"};
226 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
228 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
230 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
231 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
232 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
235 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
236 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"};
238 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, requires mod_q3shader_force_terrain_alphaflag on."};
240 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)"};
241 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
243 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
244 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
245 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
246 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
249 extern cvar_t v_glslgamma;
250 extern cvar_t v_glslgamma_2d;
252 extern qboolean v_flipped_state;
254 r_framebufferstate_t r_fb;
256 /// shadow volume bsp struct with automatically growing nodes buffer
259 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
290 typedef struct r_qwskincache_s
292 char name[MAX_QPATH];
293 skinframe_t *skinframe;
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
310 const float r_d3dscreenvertex3f[12] =
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
321 for (i = 0;i < verts;i++)
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
335 for (i = 0;i < verts;i++)
345 // FIXME: move this to client?
348 if (gamemode == GAME_NEHAHRA)
350 Cvar_Set("gl_fogenable", "0");
351 Cvar_Set("gl_fogdensity", "0.2");
352 Cvar_Set("gl_fogred", "0.3");
353 Cvar_Set("gl_foggreen", "0.3");
354 Cvar_Set("gl_fogblue", "0.3");
356 r_refdef.fog_density = 0;
357 r_refdef.fog_red = 0;
358 r_refdef.fog_green = 0;
359 r_refdef.fog_blue = 0;
360 r_refdef.fog_alpha = 1;
361 r_refdef.fog_start = 0;
362 r_refdef.fog_end = 16384;
363 r_refdef.fog_height = 1<<30;
364 r_refdef.fog_fadedepth = 128;
365 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
368 static void R_BuildBlankTextures(void)
370 unsigned char data[4];
371 data[2] = 128; // normal X
372 data[1] = 128; // normal Y
373 data[0] = 255; // normal Z
374 data[3] = 255; // height
375 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 static void R_BuildNoTexture(void)
396 unsigned char pix[16][16][4];
397 // this makes a light grey/dark grey checkerboard texture
398 for (y = 0;y < 16;y++)
400 for (x = 0;x < 16;x++)
402 if ((y < 8) ^ (x < 8))
418 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
421 static void R_BuildWhiteCube(void)
423 unsigned char data[6*1*1*4];
424 memset(data, 255, sizeof(data));
425 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
428 static void R_BuildNormalizationCube(void)
432 vec_t s, t, intensity;
435 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436 for (side = 0;side < 6;side++)
438 for (y = 0;y < NORMSIZE;y++)
440 for (x = 0;x < NORMSIZE;x++)
442 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
478 intensity = 127.0f / sqrt(DotProduct(v, v));
479 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482 data[((side*64+y)*64+x)*4+3] = 255;
486 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
490 static void R_BuildFogTexture(void)
494 unsigned char data1[FOGWIDTH][4];
495 //unsigned char data2[FOGWIDTH][4];
498 r_refdef.fogmasktable_start = r_refdef.fog_start;
499 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500 r_refdef.fogmasktable_range = r_refdef.fogrange;
501 r_refdef.fogmasktable_density = r_refdef.fog_density;
503 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506 d = (x * r - r_refdef.fogmasktable_start);
507 if(developer_extra.integer)
508 Con_DPrintf("%f ", d);
510 if (r_fog_exp2.integer)
511 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514 if(developer_extra.integer)
515 Con_DPrintf(" : %f ", alpha);
516 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517 if(developer_extra.integer)
518 Con_DPrintf(" = %f\n", alpha);
519 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
522 for (x = 0;x < FOGWIDTH;x++)
524 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529 //data2[x][0] = 255 - b;
530 //data2[x][1] = 255 - b;
531 //data2[x][2] = 255 - b;
534 if (r_texture_fogattenuation)
536 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
546 static void R_BuildFogHeightTexture(void)
548 unsigned char *inpixels;
556 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557 if (r_refdef.fogheighttexturename[0])
558 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
561 r_refdef.fog_height_tablesize = 0;
562 if (r_texture_fogheighttexture)
563 R_FreeTexture(r_texture_fogheighttexture);
564 r_texture_fogheighttexture = NULL;
565 if (r_refdef.fog_height_table2d)
566 Mem_Free(r_refdef.fog_height_table2d);
567 r_refdef.fog_height_table2d = NULL;
568 if (r_refdef.fog_height_table1d)
569 Mem_Free(r_refdef.fog_height_table1d);
570 r_refdef.fog_height_table1d = NULL;
574 r_refdef.fog_height_tablesize = size;
575 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579 // LordHavoc: now the magic - what is that table2d for? it is a cooked
580 // average fog color table accounting for every fog layer between a point
581 // and the camera. (Note: attenuation is handled separately!)
582 for (y = 0;y < size;y++)
584 for (x = 0;x < size;x++)
590 for (j = x;j <= y;j++)
592 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
598 for (j = x;j >= y;j--)
600 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
611 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
614 //=======================================================================================================================================================
616 static const char *builtinshaderstrings[] =
618 #include "shader_glsl.h"
622 const char *builtinhlslshaderstrings[] =
624 #include "shader_hlsl.h"
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
631 //=======================================================================================================================================================
633 typedef struct shaderpermutationinfo_s
638 shaderpermutationinfo_t;
640 typedef struct shadermodeinfo_s
642 const char *filename;
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {"#define USEDIFFUSE\n", " diffuse"},
652 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653 {"#define USEVIEWTINT\n", " viewtint"},
654 {"#define USECOLORMAPPING\n", " colormapping"},
655 {"#define USESATURATION\n", " saturation"},
656 {"#define USEFOGINSIDE\n", " foginside"},
657 {"#define USEFOGOUTSIDE\n", " fogoutside"},
658 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660 {"#define USEGAMMARAMPS\n", " gammaramps"},
661 {"#define USECUBEFILTER\n", " cubefilter"},
662 {"#define USEGLOW\n", " glow"},
663 {"#define USEBLOOM\n", " bloom"},
664 {"#define USESPECULAR\n", " specular"},
665 {"#define USEPOSTPROCESSING\n", " postprocessing"},
666 {"#define USEREFLECTION\n", " reflection"},
667 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
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"}, // TODO make this a static parm
678 {"#define USETRIPPY\n", " trippy"},
679 {"#define USEDEPTHRGB\n", " depthrgb"},
680 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
681 {"#define USESKELETAL\n", " skeletal"}
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
687 {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688 {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689 {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690 {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691 {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692 {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693 {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
697 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
698 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
699 {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
700 {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
701 {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
702 {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703 {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
708 {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709 {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710 {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711 {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712 {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713 {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714 {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720 {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721 {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722 {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723 {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724 {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
727 struct r_glsl_permutation_s;
728 typedef struct r_glsl_permutation_s
731 struct r_glsl_permutation_s *hashnext;
733 unsigned int permutation;
735 /// indicates if we have tried compiling this permutation already
737 /// 0 if compilation failed
739 // texture units assigned to each detected uniform
740 int tex_Texture_First;
741 int tex_Texture_Second;
742 int tex_Texture_GammaRamps;
743 int tex_Texture_Normal;
744 int tex_Texture_Color;
745 int tex_Texture_Gloss;
746 int tex_Texture_Glow;
747 int tex_Texture_SecondaryNormal;
748 int tex_Texture_SecondaryColor;
749 int tex_Texture_SecondaryGloss;
750 int tex_Texture_SecondaryGlow;
751 int tex_Texture_Pants;
752 int tex_Texture_Shirt;
753 int tex_Texture_FogHeightTexture;
754 int tex_Texture_FogMask;
755 int tex_Texture_Lightmap;
756 int tex_Texture_Deluxemap;
757 int tex_Texture_Attenuation;
758 int tex_Texture_Cube;
759 int tex_Texture_Refraction;
760 int tex_Texture_Reflection;
761 int tex_Texture_ShadowMap2D;
762 int tex_Texture_CubeProjection;
763 int tex_Texture_ScreenNormalMap;
764 int tex_Texture_ScreenDiffuse;
765 int tex_Texture_ScreenSpecular;
766 int tex_Texture_ReflectMask;
767 int tex_Texture_ReflectCube;
768 int tex_Texture_BounceGrid;
769 /// locations of detected uniforms in program object, or -1 if not found
770 int loc_Texture_First;
771 int loc_Texture_Second;
772 int loc_Texture_GammaRamps;
773 int loc_Texture_Normal;
774 int loc_Texture_Color;
775 int loc_Texture_Gloss;
776 int loc_Texture_Glow;
777 int loc_Texture_SecondaryNormal;
778 int loc_Texture_SecondaryColor;
779 int loc_Texture_SecondaryGloss;
780 int loc_Texture_SecondaryGlow;
781 int loc_Texture_Pants;
782 int loc_Texture_Shirt;
783 int loc_Texture_FogHeightTexture;
784 int loc_Texture_FogMask;
785 int loc_Texture_Lightmap;
786 int loc_Texture_Deluxemap;
787 int loc_Texture_Attenuation;
788 int loc_Texture_Cube;
789 int loc_Texture_Refraction;
790 int loc_Texture_Reflection;
791 int loc_Texture_ShadowMap2D;
792 int loc_Texture_CubeProjection;
793 int loc_Texture_ScreenNormalMap;
794 int loc_Texture_ScreenDiffuse;
795 int loc_Texture_ScreenSpecular;
796 int loc_Texture_ReflectMask;
797 int loc_Texture_ReflectCube;
798 int loc_Texture_BounceGrid;
800 int loc_BloomBlur_Parameters;
802 int loc_Color_Ambient;
803 int loc_Color_Diffuse;
804 int loc_Color_Specular;
808 int loc_DeferredColor_Ambient;
809 int loc_DeferredColor_Diffuse;
810 int loc_DeferredColor_Specular;
811 int loc_DeferredMod_Diffuse;
812 int loc_DeferredMod_Specular;
813 int loc_DistortScaleRefractReflect;
816 int loc_FogHeightFade;
818 int loc_FogPlaneViewDist;
819 int loc_FogRangeRecip;
822 int loc_LightPosition;
823 int loc_OffsetMapping_ScaleSteps;
824 int loc_OffsetMapping_LodDistance;
825 int loc_OffsetMapping_Bias;
827 int loc_ReflectColor;
828 int loc_ReflectFactor;
829 int loc_ReflectOffset;
830 int loc_RefractColor;
832 int loc_ScreenCenterRefractReflect;
833 int loc_ScreenScaleRefractReflect;
834 int loc_ScreenToDepth;
835 int loc_ShadowMap_Parameters;
836 int loc_ShadowMap_TextureScale;
837 int loc_SpecularPower;
838 int loc_Skeletal_Transform12;
843 int loc_ViewTintColor;
845 int loc_ModelToLight;
847 int loc_BackgroundTexMatrix;
848 int loc_ModelViewProjectionMatrix;
849 int loc_ModelViewMatrix;
850 int loc_PixelToScreenTexCoord;
851 int loc_ModelToReflectCube;
852 int loc_ShadowMapMatrix;
853 int loc_BloomColorSubtract;
854 int loc_NormalmapScrollBlend;
855 int loc_BounceGridMatrix;
856 int loc_BounceGridIntensity;
857 /// uniform block bindings
858 int ubibind_Skeletal_Transform12_UniformBlock;
859 /// uniform block indices
860 int ubiloc_Skeletal_Transform12_UniformBlock;
862 r_glsl_permutation_t;
864 #define SHADERPERMUTATION_HASHSIZE 256
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
871 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
877 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
879 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
880 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
881 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
882 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
883 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
885 #define SHADERSTATICPARMS_COUNT 13
887 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
888 static int shaderstaticparms_count = 0;
890 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
891 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
893 extern qboolean r_shadow_shadowmapsampler;
894 extern int r_shadow_shadowmappcf;
895 qboolean R_CompileShader_CheckStaticParms(void)
897 static int r_compileshader_staticparms_save[1];
898 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
899 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
902 if (r_glsl_saturation_redcompensate.integer)
903 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
904 if (r_glsl_vertextextureblend_usebothalphas.integer)
905 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
906 if (r_shadow_glossexact.integer)
907 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
908 if (r_glsl_postprocess.integer)
910 if (r_glsl_postprocess_uservec1_enable.integer)
911 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
912 if (r_glsl_postprocess_uservec2_enable.integer)
913 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
914 if (r_glsl_postprocess_uservec3_enable.integer)
915 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
916 if (r_glsl_postprocess_uservec4_enable.integer)
917 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
919 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
920 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
922 if (r_shadow_shadowmapsampler)
923 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
924 if (r_shadow_shadowmappcf > 1)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
926 else if (r_shadow_shadowmappcf)
927 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
928 if (r_celshading.integer)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
930 if (r_celoutlines.integer)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
933 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
936 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
937 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
938 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
940 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
941 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
943 shaderstaticparms_count = 0;
946 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
947 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
948 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
949 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
950 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
951 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
952 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
953 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
954 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
955 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
956 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
957 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
958 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
961 /// information about each possible shader permutation
962 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
963 /// currently selected permutation
964 r_glsl_permutation_t *r_glsl_permutation;
965 /// storage for permutations linked in the hash table
966 memexpandablearray_t r_glsl_permutationarray;
968 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
970 //unsigned int hashdepth = 0;
971 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
972 r_glsl_permutation_t *p;
973 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
975 if (p->mode == mode && p->permutation == permutation)
977 //if (hashdepth > 10)
978 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
983 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
985 p->permutation = permutation;
986 p->hashnext = r_glsl_permutationhash[mode][hashindex];
987 r_glsl_permutationhash[mode][hashindex] = p;
988 //if (hashdepth > 10)
989 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
993 static char *R_ShaderStrCat(const char **strings)
996 const char **p = strings;
999 for (p = strings;(t = *p);p++)
1002 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1004 for (p = strings;(t = *p);p++)
1014 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1017 if (!filename || !filename[0])
1019 // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1020 if (!strcmp(filename, "glsl/default.glsl"))
1023 return R_ShaderStrCat(builtinshaderstrings);
1024 if (!glslshaderstring)
1026 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1027 if (glslshaderstring)
1028 Con_DPrintf("Loading shaders from file %s...\n", filename);
1030 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1032 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1033 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1034 return shaderstring;
1036 if (!strcmp(filename, "hlsl/default.hlsl"))
1039 return R_ShaderStrCat(builtinhlslshaderstrings);
1040 if (!hlslshaderstring)
1042 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1043 if (hlslshaderstring)
1044 Con_DPrintf("Loading shaders from file %s...\n", filename);
1046 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1048 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1049 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1050 return shaderstring;
1052 // we don't have builtin strings for any other files
1055 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1058 if (printfromdisknotice)
1059 Con_DPrintf("from disk %s... ", filename);
1060 return shaderstring;
1062 return shaderstring;
1065 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1070 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1072 char permutationname[256];
1073 int vertstrings_count = 0;
1074 int geomstrings_count = 0;
1075 int fragstrings_count = 0;
1076 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1077 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1078 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1085 permutationname[0] = 0;
1086 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1088 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1090 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1091 if(vid.support.glshaderversion >= 140)
1093 vertstrings_list[vertstrings_count++] = "#version 140\n";
1094 geomstrings_list[geomstrings_count++] = "#version 140\n";
1095 fragstrings_list[fragstrings_count++] = "#version 140\n";
1096 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1097 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1098 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1100 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1101 else if(vid.support.glshaderversion >= 130)
1103 vertstrings_list[vertstrings_count++] = "#version 130\n";
1104 geomstrings_list[geomstrings_count++] = "#version 130\n";
1105 fragstrings_list[fragstrings_count++] = "#version 130\n";
1106 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1107 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1108 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1111 // the first pretext is which type of shader to compile as
1112 // (later these will all be bound together as a program object)
1113 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1114 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1115 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1117 // the second pretext is the mode (for example a light source)
1118 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1119 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1120 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1121 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1123 // now add all the permutation pretexts
1124 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1126 if (permutation & (1<<i))
1128 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1129 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1130 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1131 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1135 // keep line numbers correct
1136 vertstrings_list[vertstrings_count++] = "\n";
1137 geomstrings_list[geomstrings_count++] = "\n";
1138 fragstrings_list[fragstrings_count++] = "\n";
1143 R_CompileShader_AddStaticParms(mode, permutation);
1144 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1145 vertstrings_count += shaderstaticparms_count;
1146 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1147 geomstrings_count += shaderstaticparms_count;
1148 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149 fragstrings_count += shaderstaticparms_count;
1151 // now append the shader text itself
1152 vertstrings_list[vertstrings_count++] = sourcestring;
1153 geomstrings_list[geomstrings_count++] = sourcestring;
1154 fragstrings_list[fragstrings_count++] = sourcestring;
1156 // compile the shader program
1157 if (vertstrings_count + geomstrings_count + fragstrings_count)
1158 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1162 qglUseProgram(p->program);CHECKGLERROR
1163 // look up all the uniform variable names we care about, so we don't
1164 // have to look them up every time we set them
1166 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1167 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1168 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1169 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1170 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1171 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1172 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1173 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1174 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1175 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1176 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1177 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1178 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1179 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1180 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1181 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1182 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1183 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1184 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1185 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1186 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1187 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1188 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1189 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1190 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1191 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1192 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1193 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1194 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1195 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1196 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1197 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1198 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1199 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1200 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1201 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1202 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1203 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1204 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1205 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1206 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1207 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1208 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1209 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1210 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1211 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1212 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1213 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1214 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1215 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1216 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1217 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1218 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1219 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1220 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1221 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1222 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1223 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1224 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1225 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1226 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1227 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1228 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1229 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1230 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1231 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1232 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1233 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1234 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1235 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1236 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1237 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1238 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1239 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1240 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1241 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1242 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1243 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1244 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1245 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1246 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1247 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1248 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1249 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1250 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1251 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1252 // initialize the samplers to refer to the texture units we use
1253 p->tex_Texture_First = -1;
1254 p->tex_Texture_Second = -1;
1255 p->tex_Texture_GammaRamps = -1;
1256 p->tex_Texture_Normal = -1;
1257 p->tex_Texture_Color = -1;
1258 p->tex_Texture_Gloss = -1;
1259 p->tex_Texture_Glow = -1;
1260 p->tex_Texture_SecondaryNormal = -1;
1261 p->tex_Texture_SecondaryColor = -1;
1262 p->tex_Texture_SecondaryGloss = -1;
1263 p->tex_Texture_SecondaryGlow = -1;
1264 p->tex_Texture_Pants = -1;
1265 p->tex_Texture_Shirt = -1;
1266 p->tex_Texture_FogHeightTexture = -1;
1267 p->tex_Texture_FogMask = -1;
1268 p->tex_Texture_Lightmap = -1;
1269 p->tex_Texture_Deluxemap = -1;
1270 p->tex_Texture_Attenuation = -1;
1271 p->tex_Texture_Cube = -1;
1272 p->tex_Texture_Refraction = -1;
1273 p->tex_Texture_Reflection = -1;
1274 p->tex_Texture_ShadowMap2D = -1;
1275 p->tex_Texture_CubeProjection = -1;
1276 p->tex_Texture_ScreenNormalMap = -1;
1277 p->tex_Texture_ScreenDiffuse = -1;
1278 p->tex_Texture_ScreenSpecular = -1;
1279 p->tex_Texture_ReflectMask = -1;
1280 p->tex_Texture_ReflectCube = -1;
1281 p->tex_Texture_BounceGrid = -1;
1282 // bind the texture samplers in use
1284 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1285 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1286 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1287 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1288 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1289 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1290 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1291 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1292 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1293 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1294 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1295 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1296 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1297 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1298 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1299 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1300 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1301 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1302 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1303 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1304 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1305 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1306 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1307 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1308 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1309 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1310 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1311 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1312 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1313 // get the uniform block indices so we can bind them
1314 if (vid.support.arb_uniform_buffer_object)
1315 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1317 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1318 // clear the uniform block bindings
1319 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1320 // bind the uniform blocks in use
1322 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1323 // we're done compiling and setting up the shader, at least until it is used
1325 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1328 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1332 Mem_Free(sourcestring);
1335 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1337 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1338 if (r_glsl_permutation != perm)
1340 r_glsl_permutation = perm;
1341 if (!r_glsl_permutation->program)
1343 if (!r_glsl_permutation->compiled)
1344 R_GLSL_CompilePermutation(perm, mode, permutation);
1345 if (!r_glsl_permutation->program)
1347 // remove features until we find a valid permutation
1349 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1351 // reduce i more quickly whenever it would not remove any bits
1352 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1353 if (!(permutation & j))
1356 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1357 if (!r_glsl_permutation->compiled)
1358 R_GLSL_CompilePermutation(perm, mode, permutation);
1359 if (r_glsl_permutation->program)
1362 if (i >= SHADERPERMUTATION_COUNT)
1364 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1365 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1366 qglUseProgram(0);CHECKGLERROR
1367 return; // no bit left to clear, entire mode is broken
1372 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1374 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1375 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1376 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1384 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1385 extern D3DCAPS9 vid_d3d9caps;
1388 struct r_hlsl_permutation_s;
1389 typedef struct r_hlsl_permutation_s
1391 /// hash lookup data
1392 struct r_hlsl_permutation_s *hashnext;
1394 unsigned int permutation;
1396 /// indicates if we have tried compiling this permutation already
1398 /// NULL if compilation failed
1399 IDirect3DVertexShader9 *vertexshader;
1400 IDirect3DPixelShader9 *pixelshader;
1402 r_hlsl_permutation_t;
1404 typedef enum D3DVSREGISTER_e
1406 D3DVSREGISTER_TexMatrix = 0, // float4x4
1407 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1408 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1409 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1410 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1411 D3DVSREGISTER_ModelToLight = 20, // float4x4
1412 D3DVSREGISTER_EyePosition = 24,
1413 D3DVSREGISTER_FogPlane = 25,
1414 D3DVSREGISTER_LightDir = 26,
1415 D3DVSREGISTER_LightPosition = 27,
1419 typedef enum D3DPSREGISTER_e
1421 D3DPSREGISTER_Alpha = 0,
1422 D3DPSREGISTER_BloomBlur_Parameters = 1,
1423 D3DPSREGISTER_ClientTime = 2,
1424 D3DPSREGISTER_Color_Ambient = 3,
1425 D3DPSREGISTER_Color_Diffuse = 4,
1426 D3DPSREGISTER_Color_Specular = 5,
1427 D3DPSREGISTER_Color_Glow = 6,
1428 D3DPSREGISTER_Color_Pants = 7,
1429 D3DPSREGISTER_Color_Shirt = 8,
1430 D3DPSREGISTER_DeferredColor_Ambient = 9,
1431 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1432 D3DPSREGISTER_DeferredColor_Specular = 11,
1433 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1434 D3DPSREGISTER_DeferredMod_Specular = 13,
1435 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1436 D3DPSREGISTER_EyePosition = 15, // unused
1437 D3DPSREGISTER_FogColor = 16,
1438 D3DPSREGISTER_FogHeightFade = 17,
1439 D3DPSREGISTER_FogPlane = 18,
1440 D3DPSREGISTER_FogPlaneViewDist = 19,
1441 D3DPSREGISTER_FogRangeRecip = 20,
1442 D3DPSREGISTER_LightColor = 21,
1443 D3DPSREGISTER_LightDir = 22, // unused
1444 D3DPSREGISTER_LightPosition = 23,
1445 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1446 D3DPSREGISTER_PixelSize = 25,
1447 D3DPSREGISTER_ReflectColor = 26,
1448 D3DPSREGISTER_ReflectFactor = 27,
1449 D3DPSREGISTER_ReflectOffset = 28,
1450 D3DPSREGISTER_RefractColor = 29,
1451 D3DPSREGISTER_Saturation = 30,
1452 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1453 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1454 D3DPSREGISTER_ScreenToDepth = 33,
1455 D3DPSREGISTER_ShadowMap_Parameters = 34,
1456 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1457 D3DPSREGISTER_SpecularPower = 36,
1458 D3DPSREGISTER_UserVec1 = 37,
1459 D3DPSREGISTER_UserVec2 = 38,
1460 D3DPSREGISTER_UserVec3 = 39,
1461 D3DPSREGISTER_UserVec4 = 40,
1462 D3DPSREGISTER_ViewTintColor = 41,
1463 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1464 D3DPSREGISTER_BloomColorSubtract = 43,
1465 D3DPSREGISTER_ViewToLight = 44, // float4x4
1466 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1467 D3DPSREGISTER_NormalmapScrollBlend = 52,
1468 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1469 D3DPSREGISTER_OffsetMapping_Bias = 54,
1474 /// information about each possible shader permutation
1475 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1476 /// currently selected permutation
1477 r_hlsl_permutation_t *r_hlsl_permutation;
1478 /// storage for permutations linked in the hash table
1479 memexpandablearray_t r_hlsl_permutationarray;
1481 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1483 //unsigned int hashdepth = 0;
1484 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1485 r_hlsl_permutation_t *p;
1486 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1488 if (p->mode == mode && p->permutation == permutation)
1490 //if (hashdepth > 10)
1491 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1496 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1498 p->permutation = permutation;
1499 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1500 r_hlsl_permutationhash[mode][hashindex] = p;
1501 //if (hashdepth > 10)
1502 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1507 //#include <d3dx9shader.h>
1508 //#include <d3dx9mesh.h>
1510 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1512 DWORD *vsbin = NULL;
1513 DWORD *psbin = NULL;
1514 fs_offset_t vsbinsize;
1515 fs_offset_t psbinsize;
1516 // IDirect3DVertexShader9 *vs = NULL;
1517 // IDirect3DPixelShader9 *ps = NULL;
1518 ID3DXBuffer *vslog = NULL;
1519 ID3DXBuffer *vsbuffer = NULL;
1520 ID3DXConstantTable *vsconstanttable = NULL;
1521 ID3DXBuffer *pslog = NULL;
1522 ID3DXBuffer *psbuffer = NULL;
1523 ID3DXConstantTable *psconstanttable = NULL;
1526 char temp[MAX_INPUTLINE];
1527 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1529 qboolean debugshader = gl_paranoid.integer != 0;
1530 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1531 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1534 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1535 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1537 if ((!vsbin && vertstring) || (!psbin && fragstring))
1539 const char* dllnames_d3dx9 [] =
1563 dllhandle_t d3dx9_dll = NULL;
1564 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1565 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1566 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1567 dllfunction_t d3dx9_dllfuncs[] =
1569 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1570 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1571 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1574 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1575 #ifndef ID3DXBuffer_GetBufferPointer
1576 #if !defined(__cplusplus) || defined(CINTERFACE)
1577 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1578 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1579 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1581 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1582 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1583 #define ID3DXBuffer_Release(p) (p)->Release()
1586 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1588 DWORD shaderflags = 0;
1590 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1591 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1592 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1593 if (vertstring && vertstring[0])
1597 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1598 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1601 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1604 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1605 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1606 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1607 ID3DXBuffer_Release(vsbuffer);
1611 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1612 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1613 ID3DXBuffer_Release(vslog);
1616 if (fragstring && fragstring[0])
1620 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1621 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1624 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1627 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1628 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1629 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1630 ID3DXBuffer_Release(psbuffer);
1634 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1635 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1636 ID3DXBuffer_Release(pslog);
1639 Sys_UnloadLibrary(&d3dx9_dll);
1642 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1646 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1647 if (FAILED(vsresult))
1648 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1649 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1650 if (FAILED(psresult))
1651 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1653 // free the shader data
1654 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1655 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1658 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1661 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1662 int vertstring_length = 0;
1663 int geomstring_length = 0;
1664 int fragstring_length = 0;
1667 char *vertstring, *geomstring, *fragstring;
1668 char permutationname[256];
1669 char cachename[256];
1670 int vertstrings_count = 0;
1671 int geomstrings_count = 0;
1672 int fragstrings_count = 0;
1673 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1674 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1675 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1680 p->vertexshader = NULL;
1681 p->pixelshader = NULL;
1683 permutationname[0] = 0;
1685 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1687 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1688 strlcat(cachename, "hlsl/", sizeof(cachename));
1690 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1691 vertstrings_count = 0;
1692 geomstrings_count = 0;
1693 fragstrings_count = 0;
1694 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1695 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1696 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1698 // the first pretext is which type of shader to compile as
1699 // (later these will all be bound together as a program object)
1700 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1701 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1702 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1704 // the second pretext is the mode (for example a light source)
1705 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1706 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1707 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1708 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1709 strlcat(cachename, modeinfo->name, sizeof(cachename));
1711 // now add all the permutation pretexts
1712 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1714 if (permutation & (1<<i))
1716 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1717 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1718 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1719 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1720 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1724 // keep line numbers correct
1725 vertstrings_list[vertstrings_count++] = "\n";
1726 geomstrings_list[geomstrings_count++] = "\n";
1727 fragstrings_list[fragstrings_count++] = "\n";
1732 R_CompileShader_AddStaticParms(mode, permutation);
1733 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1734 vertstrings_count += shaderstaticparms_count;
1735 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1736 geomstrings_count += shaderstaticparms_count;
1737 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1738 fragstrings_count += shaderstaticparms_count;
1740 // replace spaces in the cachename with _ characters
1741 for (i = 0;cachename[i];i++)
1742 if (cachename[i] == ' ')
1745 // now append the shader text itself
1746 vertstrings_list[vertstrings_count++] = sourcestring;
1747 geomstrings_list[geomstrings_count++] = sourcestring;
1748 fragstrings_list[fragstrings_count++] = sourcestring;
1750 vertstring_length = 0;
1751 for (i = 0;i < vertstrings_count;i++)
1752 vertstring_length += strlen(vertstrings_list[i]);
1753 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1754 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1755 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1757 geomstring_length = 0;
1758 for (i = 0;i < geomstrings_count;i++)
1759 geomstring_length += strlen(geomstrings_list[i]);
1760 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1761 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1762 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1764 fragstring_length = 0;
1765 for (i = 0;i < fragstrings_count;i++)
1766 fragstring_length += strlen(fragstrings_list[i]);
1767 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1768 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1769 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1771 // try to load the cached shader, or generate one
1772 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1774 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1775 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1777 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1781 Mem_Free(vertstring);
1783 Mem_Free(geomstring);
1785 Mem_Free(fragstring);
1787 Mem_Free(sourcestring);
1790 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1791 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1792 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);}
1793 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);}
1794 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);}
1795 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);}
1797 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1798 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1799 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);}
1800 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);}
1801 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);}
1802 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);}
1804 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1806 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1807 if (r_hlsl_permutation != perm)
1809 r_hlsl_permutation = perm;
1810 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1812 if (!r_hlsl_permutation->compiled)
1813 R_HLSL_CompilePermutation(perm, mode, permutation);
1814 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1816 // remove features until we find a valid permutation
1818 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1820 // reduce i more quickly whenever it would not remove any bits
1821 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1822 if (!(permutation & j))
1825 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1826 if (!r_hlsl_permutation->compiled)
1827 R_HLSL_CompilePermutation(perm, mode, permutation);
1828 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1831 if (i >= SHADERPERMUTATION_COUNT)
1833 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1834 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1835 return; // no bit left to clear, entire mode is broken
1839 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1840 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1842 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1843 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1844 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1848 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1850 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1851 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1852 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1853 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1856 void R_GLSL_Restart_f(void)
1858 unsigned int i, limit;
1859 if (glslshaderstring)
1860 Mem_Free(glslshaderstring);
1861 glslshaderstring = NULL;
1862 if (hlslshaderstring)
1863 Mem_Free(hlslshaderstring);
1864 hlslshaderstring = NULL;
1865 switch(vid.renderpath)
1867 case RENDERPATH_D3D9:
1870 r_hlsl_permutation_t *p;
1871 r_hlsl_permutation = NULL;
1872 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1873 for (i = 0;i < limit;i++)
1875 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1877 if (p->vertexshader)
1878 IDirect3DVertexShader9_Release(p->vertexshader);
1880 IDirect3DPixelShader9_Release(p->pixelshader);
1881 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1884 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1888 case RENDERPATH_D3D10:
1889 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1891 case RENDERPATH_D3D11:
1892 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1894 case RENDERPATH_GL20:
1895 case RENDERPATH_GLES2:
1897 r_glsl_permutation_t *p;
1898 r_glsl_permutation = NULL;
1899 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1900 for (i = 0;i < limit;i++)
1902 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1904 GL_Backend_FreeProgram(p->program);
1905 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1908 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1911 case RENDERPATH_GL11:
1912 case RENDERPATH_GL13:
1913 case RENDERPATH_GLES1:
1915 case RENDERPATH_SOFT:
1920 static void R_GLSL_DumpShader_f(void)
1922 int i, language, mode, dupe;
1924 shadermodeinfo_t *modeinfo;
1927 for (language = 0;language < 2;language++)
1929 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1930 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1932 // don't dump the same file multiple times (most or all shaders come from the same file)
1933 for (dupe = mode - 1;dupe >= 0;dupe--)
1934 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1938 text = R_GetShaderText(modeinfo[mode].filename, false, true);
1941 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1944 FS_Print(file, "/* The engine may define the following macros:\n");
1945 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1946 for (i = 0;i < SHADERMODE_COUNT;i++)
1947 FS_Print(file, modeinfo[i].pretext);
1948 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1949 FS_Print(file, shaderpermutationinfo[i].pretext);
1950 FS_Print(file, "*/\n");
1951 FS_Print(file, text);
1953 Con_Printf("%s written\n", modeinfo[mode].filename);
1956 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1962 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1964 unsigned int permutation = 0;
1965 if (r_trippy.integer && !notrippy)
1966 permutation |= SHADERPERMUTATION_TRIPPY;
1967 permutation |= SHADERPERMUTATION_VIEWTINT;
1969 permutation |= SHADERPERMUTATION_DIFFUSE;
1971 permutation |= SHADERPERMUTATION_SPECULAR;
1972 if (texturemode == GL_MODULATE)
1973 permutation |= SHADERPERMUTATION_COLORMAPPING;
1974 else if (texturemode == GL_ADD)
1975 permutation |= SHADERPERMUTATION_GLOW;
1976 else if (texturemode == GL_DECAL)
1977 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1978 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1979 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1980 if (suppresstexalpha)
1981 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1983 texturemode = GL_MODULATE;
1984 if (vid.allowalphatocoverage)
1985 GL_AlphaToCoverage(false);
1986 switch (vid.renderpath)
1988 case RENDERPATH_D3D9:
1990 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1991 R_Mesh_TexBind(GL20TU_FIRST , first );
1992 R_Mesh_TexBind(GL20TU_SECOND, second);
1993 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1994 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1997 case RENDERPATH_D3D10:
1998 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2000 case RENDERPATH_D3D11:
2001 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2003 case RENDERPATH_GL20:
2004 case RENDERPATH_GLES2:
2005 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2006 if (r_glsl_permutation->tex_Texture_First >= 0)
2007 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2008 if (r_glsl_permutation->tex_Texture_Second >= 0)
2009 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2010 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2011 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2013 case RENDERPATH_GL13:
2014 case RENDERPATH_GLES1:
2015 R_Mesh_TexBind(0, first );
2016 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2017 R_Mesh_TexMatrix(0, NULL);
2018 R_Mesh_TexBind(1, second);
2021 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2022 R_Mesh_TexMatrix(1, NULL);
2025 case RENDERPATH_GL11:
2026 R_Mesh_TexBind(0, first );
2027 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2028 R_Mesh_TexMatrix(0, NULL);
2030 case RENDERPATH_SOFT:
2031 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2032 R_Mesh_TexBind(GL20TU_FIRST , first );
2033 R_Mesh_TexBind(GL20TU_SECOND, second);
2038 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2040 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2043 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2045 unsigned int permutation = 0;
2046 if (r_trippy.integer && !notrippy)
2047 permutation |= SHADERPERMUTATION_TRIPPY;
2049 permutation |= SHADERPERMUTATION_DEPTHRGB;
2051 permutation |= SHADERPERMUTATION_SKELETAL;
2053 if (vid.allowalphatocoverage)
2054 GL_AlphaToCoverage(false);
2055 switch (vid.renderpath)
2057 case RENDERPATH_D3D9:
2059 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2062 case RENDERPATH_D3D10:
2063 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2065 case RENDERPATH_D3D11:
2066 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2068 case RENDERPATH_GL20:
2069 case RENDERPATH_GLES2:
2070 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2071 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2073 case RENDERPATH_GL13:
2074 case RENDERPATH_GLES1:
2075 R_Mesh_TexBind(0, 0);
2076 R_Mesh_TexBind(1, 0);
2078 case RENDERPATH_GL11:
2079 R_Mesh_TexBind(0, 0);
2081 case RENDERPATH_SOFT:
2082 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2087 extern qboolean r_shadow_usingdeferredprepass;
2088 extern rtexture_t *r_shadow_attenuationgradienttexture;
2089 extern rtexture_t *r_shadow_attenuation2dtexture;
2090 extern rtexture_t *r_shadow_attenuation3dtexture;
2091 extern qboolean r_shadow_usingshadowmap2d;
2092 extern qboolean r_shadow_usingshadowmaportho;
2093 extern float r_shadow_shadowmap_texturescale[2];
2094 extern float r_shadow_shadowmap_parameters[4];
2095 extern qboolean r_shadow_shadowmapvsdct;
2096 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2097 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2098 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2099 extern matrix4x4_t r_shadow_shadowmapmatrix;
2100 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2101 extern int r_shadow_prepass_width;
2102 extern int r_shadow_prepass_height;
2103 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2104 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2105 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2106 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2108 #define BLENDFUNC_ALLOWS_COLORMOD 1
2109 #define BLENDFUNC_ALLOWS_FOG 2
2110 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2111 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2112 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2113 static int R_BlendFuncFlags(int src, int dst)
2117 // a blendfunc allows colormod if:
2118 // a) it can never keep the destination pixel invariant, or
2119 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2120 // this is to prevent unintended side effects from colormod
2122 // a blendfunc allows fog if:
2123 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2124 // this is to prevent unintended side effects from fog
2126 // these checks are the output of fogeval.pl
2128 r |= BLENDFUNC_ALLOWS_COLORMOD;
2129 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2130 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2131 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2132 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2133 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2134 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2135 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2136 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2137 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2138 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2139 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2140 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2141 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2142 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2143 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2144 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2145 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2146 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2147 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2148 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2149 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2154 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)
2156 // select a permutation of the lighting shader appropriate to this
2157 // combination of texture, entity, light source, and fogging, only use the
2158 // minimum features necessary to avoid wasting rendering time in the
2159 // fragment shader on features that are not being used
2160 unsigned int permutation = 0;
2161 unsigned int mode = 0;
2163 static float dummy_colormod[3] = {1, 1, 1};
2164 float *colormod = rsurface.colormod;
2166 matrix4x4_t tempmatrix;
2167 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2168 if (r_trippy.integer && !notrippy)
2169 permutation |= SHADERPERMUTATION_TRIPPY;
2170 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2171 permutation |= SHADERPERMUTATION_ALPHAKILL;
2172 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2173 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2174 if (rsurfacepass == RSURFPASS_BACKGROUND)
2176 // distorted background
2177 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2179 mode = SHADERMODE_WATER;
2180 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2181 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2182 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2184 // this is the right thing to do for wateralpha
2185 GL_BlendFunc(GL_ONE, GL_ZERO);
2186 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2190 // this is the right thing to do for entity alpha
2191 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2192 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2195 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2197 mode = SHADERMODE_REFRACTION;
2198 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2199 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2200 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2201 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2205 mode = SHADERMODE_GENERIC;
2206 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2207 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2208 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2210 if (vid.allowalphatocoverage)
2211 GL_AlphaToCoverage(false);
2213 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2215 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2217 switch(rsurface.texture->offsetmapping)
2219 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2220 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2221 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2222 case OFFSETMAPPING_OFF: break;
2225 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2226 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2227 // normalmap (deferred prepass), may use alpha test on diffuse
2228 mode = SHADERMODE_DEFERREDGEOMETRY;
2229 GL_BlendFunc(GL_ONE, GL_ZERO);
2230 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2231 if (vid.allowalphatocoverage)
2232 GL_AlphaToCoverage(false);
2234 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2236 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2238 switch(rsurface.texture->offsetmapping)
2240 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2241 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2243 case OFFSETMAPPING_OFF: break;
2246 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2247 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2248 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2249 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2251 mode = SHADERMODE_LIGHTSOURCE;
2252 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2253 permutation |= SHADERPERMUTATION_CUBEFILTER;
2254 if (diffusescale > 0)
2255 permutation |= SHADERPERMUTATION_DIFFUSE;
2256 if (specularscale > 0)
2257 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2258 if (r_refdef.fogenabled)
2259 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2260 if (rsurface.texture->colormapping)
2261 permutation |= SHADERPERMUTATION_COLORMAPPING;
2262 if (r_shadow_usingshadowmap2d)
2264 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2265 if(r_shadow_shadowmapvsdct)
2266 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2268 if (r_shadow_shadowmap2ddepthbuffer)
2269 permutation |= SHADERPERMUTATION_DEPTHRGB;
2271 if (rsurface.texture->reflectmasktexture)
2272 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2273 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2274 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2275 if (vid.allowalphatocoverage)
2276 GL_AlphaToCoverage(false);
2278 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2280 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2282 switch(rsurface.texture->offsetmapping)
2284 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2285 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2287 case OFFSETMAPPING_OFF: break;
2290 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2291 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2292 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2293 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2294 // unshaded geometry (fullbright or ambient model lighting)
2295 mode = SHADERMODE_FLATCOLOR;
2296 ambientscale = diffusescale = specularscale = 0;
2297 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2298 permutation |= SHADERPERMUTATION_GLOW;
2299 if (r_refdef.fogenabled)
2300 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2301 if (rsurface.texture->colormapping)
2302 permutation |= SHADERPERMUTATION_COLORMAPPING;
2303 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2305 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2306 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2308 if (r_shadow_shadowmap2ddepthbuffer)
2309 permutation |= SHADERPERMUTATION_DEPTHRGB;
2311 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2312 permutation |= SHADERPERMUTATION_REFLECTION;
2313 if (rsurface.texture->reflectmasktexture)
2314 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2315 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2316 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2317 // when using alphatocoverage, we don't need alphakill
2318 if (vid.allowalphatocoverage)
2320 if (r_transparent_alphatocoverage.integer)
2322 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2323 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2326 GL_AlphaToCoverage(false);
2329 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2331 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2333 switch(rsurface.texture->offsetmapping)
2335 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2336 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2337 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2338 case OFFSETMAPPING_OFF: break;
2341 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2342 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2343 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2344 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2345 // directional model lighting
2346 mode = SHADERMODE_LIGHTDIRECTION;
2347 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2348 permutation |= SHADERPERMUTATION_GLOW;
2349 permutation |= SHADERPERMUTATION_DIFFUSE;
2350 if (specularscale > 0)
2351 permutation |= SHADERPERMUTATION_SPECULAR;
2352 if (r_refdef.fogenabled)
2353 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2354 if (rsurface.texture->colormapping)
2355 permutation |= SHADERPERMUTATION_COLORMAPPING;
2356 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2358 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2359 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2361 if (r_shadow_shadowmap2ddepthbuffer)
2362 permutation |= SHADERPERMUTATION_DEPTHRGB;
2364 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2365 permutation |= SHADERPERMUTATION_REFLECTION;
2366 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2367 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2368 if (rsurface.texture->reflectmasktexture)
2369 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2370 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2372 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2373 if (r_shadow_bouncegriddirectional)
2374 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2376 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2377 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2378 // when using alphatocoverage, we don't need alphakill
2379 if (vid.allowalphatocoverage)
2381 if (r_transparent_alphatocoverage.integer)
2383 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2384 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2387 GL_AlphaToCoverage(false);
2390 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2392 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2394 switch(rsurface.texture->offsetmapping)
2396 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2397 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2398 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2399 case OFFSETMAPPING_OFF: break;
2402 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2403 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2404 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2405 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2406 // ambient model lighting
2407 mode = SHADERMODE_LIGHTDIRECTION;
2408 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2409 permutation |= SHADERPERMUTATION_GLOW;
2410 if (r_refdef.fogenabled)
2411 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2412 if (rsurface.texture->colormapping)
2413 permutation |= SHADERPERMUTATION_COLORMAPPING;
2414 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2416 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2417 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2419 if (r_shadow_shadowmap2ddepthbuffer)
2420 permutation |= SHADERPERMUTATION_DEPTHRGB;
2422 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2423 permutation |= SHADERPERMUTATION_REFLECTION;
2424 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2425 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2426 if (rsurface.texture->reflectmasktexture)
2427 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2428 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2430 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2431 if (r_shadow_bouncegriddirectional)
2432 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2434 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2436 // when using alphatocoverage, we don't need alphakill
2437 if (vid.allowalphatocoverage)
2439 if (r_transparent_alphatocoverage.integer)
2441 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2442 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2445 GL_AlphaToCoverage(false);
2450 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2452 switch(rsurface.texture->offsetmapping)
2454 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2455 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2456 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2457 case OFFSETMAPPING_OFF: break;
2460 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2461 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2462 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2463 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2465 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2466 permutation |= SHADERPERMUTATION_GLOW;
2467 if (r_refdef.fogenabled)
2468 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2469 if (rsurface.texture->colormapping)
2470 permutation |= SHADERPERMUTATION_COLORMAPPING;
2471 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2473 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2474 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2476 if (r_shadow_shadowmap2ddepthbuffer)
2477 permutation |= SHADERPERMUTATION_DEPTHRGB;
2479 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2480 permutation |= SHADERPERMUTATION_REFLECTION;
2481 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2482 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2483 if (rsurface.texture->reflectmasktexture)
2484 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2485 if (FAKELIGHT_ENABLED)
2487 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2488 mode = SHADERMODE_FAKELIGHT;
2489 permutation |= SHADERPERMUTATION_DIFFUSE;
2490 if (specularscale > 0)
2491 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2493 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2495 // deluxemapping (light direction texture)
2496 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2497 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2499 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2500 permutation |= SHADERPERMUTATION_DIFFUSE;
2501 if (specularscale > 0)
2502 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2504 else if (r_glsl_deluxemapping.integer >= 2)
2506 // fake deluxemapping (uniform light direction in tangentspace)
2507 if (rsurface.uselightmaptexture)
2508 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2510 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2511 permutation |= SHADERPERMUTATION_DIFFUSE;
2512 if (specularscale > 0)
2513 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2515 else if (rsurface.uselightmaptexture)
2517 // ordinary lightmapping (q1bsp, q3bsp)
2518 mode = SHADERMODE_LIGHTMAP;
2522 // ordinary vertex coloring (q3bsp)
2523 mode = SHADERMODE_VERTEXCOLOR;
2525 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2527 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2528 if (r_shadow_bouncegriddirectional)
2529 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2531 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2532 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2533 // when using alphatocoverage, we don't need alphakill
2534 if (vid.allowalphatocoverage)
2536 if (r_transparent_alphatocoverage.integer)
2538 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2539 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2542 GL_AlphaToCoverage(false);
2545 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2546 colormod = dummy_colormod;
2547 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2548 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2549 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2550 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2551 switch(vid.renderpath)
2553 case RENDERPATH_D3D9:
2555 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2556 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2557 R_SetupShader_SetPermutationHLSL(mode, permutation);
2558 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2559 if (mode == SHADERMODE_LIGHTSOURCE)
2561 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2562 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2566 if (mode == SHADERMODE_LIGHTDIRECTION)
2568 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2571 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2572 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2573 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2574 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2575 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2577 if (mode == SHADERMODE_LIGHTSOURCE)
2579 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2580 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2581 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2582 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2583 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2585 // additive passes are only darkened by fog, not tinted
2586 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2587 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2591 if (mode == SHADERMODE_FLATCOLOR)
2593 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2595 else if (mode == SHADERMODE_LIGHTDIRECTION)
2597 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]);
2598 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2599 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);
2600 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2601 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2602 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2603 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2607 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2608 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2609 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);
2610 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2611 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2613 // additive passes are only darkened by fog, not tinted
2614 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2615 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2617 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2618 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);
2619 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2620 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2621 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2622 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2623 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2624 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2625 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2626 if (mode == SHADERMODE_WATER)
2627 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2629 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2630 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2631 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2632 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2633 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2634 if (rsurface.texture->pantstexture)
2635 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2637 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2638 if (rsurface.texture->shirttexture)
2639 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2641 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2642 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2643 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2644 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2645 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2646 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2647 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2648 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2649 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2650 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2652 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2653 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2654 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2655 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2657 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2658 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2659 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2660 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2661 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2662 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2663 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2664 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2665 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2666 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2667 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2668 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2669 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2670 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2671 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2672 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2673 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2674 if (rsurfacepass == RSURFPASS_BACKGROUND)
2676 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2677 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2678 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2682 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2684 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2685 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2686 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2687 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2689 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2690 if (rsurface.rtlight)
2692 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2693 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2698 case RENDERPATH_D3D10:
2699 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2701 case RENDERPATH_D3D11:
2702 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2704 case RENDERPATH_GL20:
2705 case RENDERPATH_GLES2:
2706 if (!vid.useinterleavedarrays)
2708 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2709 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2710 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2711 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2712 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2713 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2714 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2715 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2716 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2717 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2718 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2722 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) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2723 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2725 // this has to be after RSurf_PrepareVerticesForBatch
2726 if (rsurface.batchskeletaltransform3x4buffer)
2727 permutation |= SHADERPERMUTATION_SKELETAL;
2728 R_SetupShader_SetPermutationGLSL(mode, permutation);
2729 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2730 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2731 if (mode == SHADERMODE_LIGHTSOURCE)
2733 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2734 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2735 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2736 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2737 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2738 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);
2740 // additive passes are only darkened by fog, not tinted
2741 if (r_glsl_permutation->loc_FogColor >= 0)
2742 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2743 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2747 if (mode == SHADERMODE_FLATCOLOR)
2749 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2751 else if (mode == SHADERMODE_LIGHTDIRECTION)
2753 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]);
2754 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]);
2755 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);
2756 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2757 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2758 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]);
2759 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]);
2763 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]);
2764 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]);
2765 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);
2766 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2767 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2769 // additive passes are only darkened by fog, not tinted
2770 if (r_glsl_permutation->loc_FogColor >= 0)
2772 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2773 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2775 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2777 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);
2778 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2779 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2780 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]);
2781 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]);
2782 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2783 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2784 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2785 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]);
2787 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2788 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2789 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2790 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]);
2791 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]);
2793 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2794 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2795 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2796 if (r_glsl_permutation->loc_Color_Pants >= 0)
2798 if (rsurface.texture->pantstexture)
2799 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2801 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2803 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2805 if (rsurface.texture->shirttexture)
2806 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2808 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2810 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]);
2811 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2812 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2813 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2814 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2815 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2816 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2817 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2818 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2820 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2821 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2822 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]);
2823 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2824 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);}
2825 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2827 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2828 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2829 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2830 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2831 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2832 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2833 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2834 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2835 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2836 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2837 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2838 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2839 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2840 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2841 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);
2842 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2843 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2844 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2845 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2846 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2847 if (rsurfacepass == RSURFPASS_BACKGROUND)
2849 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);
2850 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);
2851 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);
2855 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);
2857 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2858 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2859 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2860 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2862 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2863 if (rsurface.rtlight)
2865 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2866 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2869 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2872 case RENDERPATH_GL11:
2873 case RENDERPATH_GL13:
2874 case RENDERPATH_GLES1:
2876 case RENDERPATH_SOFT:
2877 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2878 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2879 R_SetupShader_SetPermutationSoft(mode, permutation);
2880 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2881 if (mode == SHADERMODE_LIGHTSOURCE)
2883 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2884 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2885 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2886 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2887 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2888 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2890 // additive passes are only darkened by fog, not tinted
2891 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2892 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2896 if (mode == SHADERMODE_FLATCOLOR)
2898 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2900 else if (mode == SHADERMODE_LIGHTDIRECTION)
2902 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]);
2903 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2904 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);
2905 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2906 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2907 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]);
2908 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2912 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2913 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2914 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);
2915 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2916 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2918 // additive passes are only darkened by fog, not tinted
2919 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2920 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2922 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2923 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);
2924 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2925 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2926 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]);
2927 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]);
2928 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2929 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2930 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2931 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2933 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2934 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2935 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2936 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2937 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]);
2939 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2940 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2941 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2942 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2944 if (rsurface.texture->pantstexture)
2945 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2947 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2949 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2951 if (rsurface.texture->shirttexture)
2952 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2954 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2956 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2957 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2958 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2959 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2960 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2961 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2962 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2963 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2964 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2966 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2967 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2968 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2969 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2971 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2972 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2973 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2974 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2975 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2976 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2977 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2978 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2979 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2980 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2981 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2982 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2983 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2984 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2985 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2986 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2987 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2988 if (rsurfacepass == RSURFPASS_BACKGROUND)
2990 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2991 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2992 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2996 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2998 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2999 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3000 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3001 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3003 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3004 if (rsurface.rtlight)
3006 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3007 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3014 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3016 // select a permutation of the lighting shader appropriate to this
3017 // combination of texture, entity, light source, and fogging, only use the
3018 // minimum features necessary to avoid wasting rendering time in the
3019 // fragment shader on features that are not being used
3020 unsigned int permutation = 0;
3021 unsigned int mode = 0;
3022 const float *lightcolorbase = rtlight->currentcolor;
3023 float ambientscale = rtlight->ambientscale;
3024 float diffusescale = rtlight->diffusescale;
3025 float specularscale = rtlight->specularscale;
3026 // this is the location of the light in view space
3027 vec3_t viewlightorigin;
3028 // this transforms from view space (camera) to light space (cubemap)
3029 matrix4x4_t viewtolight;
3030 matrix4x4_t lighttoview;
3031 float viewtolight16f[16];
3033 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3034 if (rtlight->currentcubemap != r_texture_whitecube)
3035 permutation |= SHADERPERMUTATION_CUBEFILTER;
3036 if (diffusescale > 0)
3037 permutation |= SHADERPERMUTATION_DIFFUSE;
3038 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3039 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3040 if (r_shadow_usingshadowmap2d)
3042 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3043 if (r_shadow_shadowmapvsdct)
3044 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3046 if (r_shadow_shadowmap2ddepthbuffer)
3047 permutation |= SHADERPERMUTATION_DEPTHRGB;
3049 if (vid.allowalphatocoverage)
3050 GL_AlphaToCoverage(false);
3051 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3052 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3053 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3054 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3055 switch(vid.renderpath)
3057 case RENDERPATH_D3D9:
3059 R_SetupShader_SetPermutationHLSL(mode, permutation);
3060 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3061 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3062 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3063 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3064 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3065 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3066 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3067 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3068 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3069 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3071 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3072 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3073 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3074 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3075 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3078 case RENDERPATH_D3D10:
3079 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3081 case RENDERPATH_D3D11:
3082 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3084 case RENDERPATH_GL20:
3085 case RENDERPATH_GLES2:
3086 R_SetupShader_SetPermutationGLSL(mode, permutation);
3087 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3088 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3089 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3090 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3091 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3092 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]);
3093 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]);
3094 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3095 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]);
3096 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3098 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3099 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3100 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3101 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3102 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3104 case RENDERPATH_GL11:
3105 case RENDERPATH_GL13:
3106 case RENDERPATH_GLES1:
3108 case RENDERPATH_SOFT:
3109 R_SetupShader_SetPermutationGLSL(mode, permutation);
3110 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3111 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3112 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3113 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3114 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3115 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3116 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]);
3117 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3118 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3119 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3121 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3122 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3123 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3124 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3125 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3130 #define SKINFRAME_HASH 1024
3134 int loadsequence; // incremented each level change
3135 memexpandablearray_t array;
3136 skinframe_t *hash[SKINFRAME_HASH];
3139 r_skinframe_t r_skinframe;
3141 void R_SkinFrame_PrepareForPurge(void)
3143 r_skinframe.loadsequence++;
3144 // wrap it without hitting zero
3145 if (r_skinframe.loadsequence >= 200)
3146 r_skinframe.loadsequence = 1;
3149 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3153 // mark the skinframe as used for the purging code
3154 skinframe->loadsequence = r_skinframe.loadsequence;
3157 void R_SkinFrame_Purge(void)
3161 for (i = 0;i < SKINFRAME_HASH;i++)
3163 for (s = r_skinframe.hash[i];s;s = s->next)
3165 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3167 if (s->merged == s->base)
3169 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3170 R_PurgeTexture(s->stain );s->stain = NULL;
3171 R_PurgeTexture(s->merged);s->merged = NULL;
3172 R_PurgeTexture(s->base );s->base = NULL;
3173 R_PurgeTexture(s->pants );s->pants = NULL;
3174 R_PurgeTexture(s->shirt );s->shirt = NULL;
3175 R_PurgeTexture(s->nmap );s->nmap = NULL;
3176 R_PurgeTexture(s->gloss );s->gloss = NULL;
3177 R_PurgeTexture(s->glow );s->glow = NULL;
3178 R_PurgeTexture(s->fog );s->fog = NULL;
3179 R_PurgeTexture(s->reflect);s->reflect = NULL;
3180 s->loadsequence = 0;
3186 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3188 char basename[MAX_QPATH];
3190 Image_StripImageExtension(name, basename, sizeof(basename));
3192 if( last == NULL ) {
3194 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3195 item = r_skinframe.hash[hashindex];
3200 // linearly search through the hash bucket
3201 for( ; item ; item = item->next ) {
3202 if( !strcmp( item->basename, basename ) ) {
3209 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3213 char basename[MAX_QPATH];
3215 Image_StripImageExtension(name, basename, sizeof(basename));
3217 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3218 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3219 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3223 rtexture_t *dyntexture;
3224 // check whether its a dynamic texture
3225 dyntexture = CL_GetDynTexture( basename );
3226 if (!add && !dyntexture)
3228 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3229 memset(item, 0, sizeof(*item));
3230 strlcpy(item->basename, basename, sizeof(item->basename));
3231 item->base = dyntexture; // either NULL or dyntexture handle
3232 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3233 item->comparewidth = comparewidth;
3234 item->compareheight = compareheight;
3235 item->comparecrc = comparecrc;
3236 item->next = r_skinframe.hash[hashindex];
3237 r_skinframe.hash[hashindex] = item;
3239 else if (textureflags & TEXF_FORCE_RELOAD)
3241 rtexture_t *dyntexture;
3242 // check whether its a dynamic texture
3243 dyntexture = CL_GetDynTexture( basename );
3244 if (!add && !dyntexture)
3246 if (item->merged == item->base)
3247 item->merged = NULL;
3248 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3249 R_PurgeTexture(item->stain );item->stain = NULL;
3250 R_PurgeTexture(item->merged);item->merged = NULL;
3251 R_PurgeTexture(item->base );item->base = NULL;
3252 R_PurgeTexture(item->pants );item->pants = NULL;
3253 R_PurgeTexture(item->shirt );item->shirt = NULL;
3254 R_PurgeTexture(item->nmap );item->nmap = NULL;
3255 R_PurgeTexture(item->gloss );item->gloss = NULL;
3256 R_PurgeTexture(item->glow );item->glow = NULL;
3257 R_PurgeTexture(item->fog );item->fog = NULL;
3258 R_PurgeTexture(item->reflect);item->reflect = NULL;
3259 item->loadsequence = 0;
3261 else if( item->base == NULL )
3263 rtexture_t *dyntexture;
3264 // check whether its a dynamic texture
3265 // 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]
3266 dyntexture = CL_GetDynTexture( basename );
3267 item->base = dyntexture; // either NULL or dyntexture handle
3270 R_SkinFrame_MarkUsed(item);
3274 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3276 unsigned long long avgcolor[5], wsum; \
3284 for(pix = 0; pix < cnt; ++pix) \
3287 for(comp = 0; comp < 3; ++comp) \
3289 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3292 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3294 for(comp = 0; comp < 3; ++comp) \
3295 avgcolor[comp] += getpixel * w; \
3298 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3299 avgcolor[4] += getpixel; \
3301 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3303 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3304 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3305 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3306 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3309 extern cvar_t gl_picmip;
3310 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3313 unsigned char *pixels;
3314 unsigned char *bumppixels;
3315 unsigned char *basepixels = NULL;
3316 int basepixels_width = 0;
3317 int basepixels_height = 0;
3318 skinframe_t *skinframe;
3319 rtexture_t *ddsbase = NULL;
3320 qboolean ddshasalpha = false;
3321 float ddsavgcolor[4];
3322 char basename[MAX_QPATH];
3323 int miplevel = R_PicmipForFlags(textureflags);
3324 int savemiplevel = miplevel;
3328 if (cls.state == ca_dedicated)
3331 // return an existing skinframe if already loaded
3332 // if loading of the first image fails, don't make a new skinframe as it
3333 // would cause all future lookups of this to be missing
3334 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3335 if (skinframe && skinframe->base)
3338 Image_StripImageExtension(name, basename, sizeof(basename));
3340 // check for DDS texture file first
3341 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3343 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3344 if (basepixels == NULL)
3348 // FIXME handle miplevel
3350 if (developer_loading.integer)
3351 Con_Printf("loading skin \"%s\"\n", name);
3353 // we've got some pixels to store, so really allocate this new texture now
3355 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3356 textureflags &= ~TEXF_FORCE_RELOAD;
3357 skinframe->stain = NULL;
3358 skinframe->merged = NULL;
3359 skinframe->base = NULL;
3360 skinframe->pants = NULL;
3361 skinframe->shirt = NULL;
3362 skinframe->nmap = NULL;
3363 skinframe->gloss = NULL;
3364 skinframe->glow = NULL;
3365 skinframe->fog = NULL;
3366 skinframe->reflect = NULL;
3367 skinframe->hasalpha = false;
3371 skinframe->base = ddsbase;
3372 skinframe->hasalpha = ddshasalpha;
3373 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3374 if (r_loadfog && skinframe->hasalpha)
3375 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3376 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3380 basepixels_width = image_width;
3381 basepixels_height = image_height;
3382 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);
3383 if (textureflags & TEXF_ALPHA)
3385 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3387 if (basepixels[j] < 255)
3389 skinframe->hasalpha = true;
3393 if (r_loadfog && skinframe->hasalpha)
3395 // has transparent pixels
3396 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3397 for (j = 0;j < image_width * image_height * 4;j += 4)
3402 pixels[j+3] = basepixels[j+3];
3404 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3408 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3410 //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]);
3411 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3412 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3413 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3414 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3420 mymiplevel = savemiplevel;
3421 if (r_loadnormalmap)
3422 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3423 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3425 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3426 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3427 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3428 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3431 // _norm is the name used by tenebrae and has been adopted as standard
3432 if (r_loadnormalmap && skinframe->nmap == NULL)
3434 mymiplevel = savemiplevel;
3435 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3437 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3441 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3443 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3444 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3445 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3447 Mem_Free(bumppixels);
3449 else if (r_shadow_bumpscale_basetexture.value > 0)
3451 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3452 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3453 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3457 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3458 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3462 // _luma is supported only for tenebrae compatibility
3463 // _glow is the preferred name
3464 mymiplevel = savemiplevel;
3465 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3467 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3469 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3470 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3472 Mem_Free(pixels);pixels = NULL;
3475 mymiplevel = savemiplevel;
3476 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3478 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3480 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3481 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3487 mymiplevel = savemiplevel;
3488 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3490 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3492 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3493 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3499 mymiplevel = savemiplevel;
3500 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3502 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3504 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3505 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3511 mymiplevel = savemiplevel;
3512 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3514 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3516 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3517 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3524 Mem_Free(basepixels);
3529 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3530 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3533 unsigned char *temp1, *temp2;
3534 skinframe_t *skinframe;
3537 if (cls.state == ca_dedicated)
3540 // if already loaded just return it, otherwise make a new skinframe
3541 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3542 if (skinframe->base)
3544 textureflags &= ~TEXF_FORCE_RELOAD;
3546 skinframe->stain = NULL;
3547 skinframe->merged = NULL;
3548 skinframe->base = NULL;
3549 skinframe->pants = NULL;
3550 skinframe->shirt = NULL;
3551 skinframe->nmap = NULL;
3552 skinframe->gloss = NULL;
3553 skinframe->glow = NULL;
3554 skinframe->fog = NULL;
3555 skinframe->reflect = NULL;
3556 skinframe->hasalpha = false;
3558 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3562 if (developer_loading.integer)
3563 Con_Printf("loading 32bit skin \"%s\"\n", name);
3565 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3567 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3568 temp2 = temp1 + width * height * 4;
3569 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3570 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3573 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3574 if (textureflags & TEXF_ALPHA)
3576 for (i = 3;i < width * height * 4;i += 4)
3578 if (skindata[i] < 255)
3580 skinframe->hasalpha = true;
3584 if (r_loadfog && skinframe->hasalpha)
3586 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3587 memcpy(fogpixels, skindata, width * height * 4);
3588 for (i = 0;i < width * height * 4;i += 4)
3589 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3590 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3591 Mem_Free(fogpixels);
3595 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3596 //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]);
3601 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3605 skinframe_t *skinframe;
3607 if (cls.state == ca_dedicated)
3610 // if already loaded just return it, otherwise make a new skinframe
3611 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3612 if (skinframe->base)
3614 //textureflags &= ~TEXF_FORCE_RELOAD;
3616 skinframe->stain = NULL;
3617 skinframe->merged = NULL;
3618 skinframe->base = NULL;
3619 skinframe->pants = NULL;
3620 skinframe->shirt = NULL;
3621 skinframe->nmap = NULL;
3622 skinframe->gloss = NULL;
3623 skinframe->glow = NULL;
3624 skinframe->fog = NULL;
3625 skinframe->reflect = NULL;
3626 skinframe->hasalpha = false;
3628 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3632 if (developer_loading.integer)
3633 Con_Printf("loading quake skin \"%s\"\n", name);
3635 // 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)
3636 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3637 memcpy(skinframe->qpixels, skindata, width*height);
3638 skinframe->qwidth = width;
3639 skinframe->qheight = height;
3642 for (i = 0;i < width * height;i++)
3643 featuresmask |= palette_featureflags[skindata[i]];
3645 skinframe->hasalpha = false;
3646 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3647 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3648 skinframe->qgeneratemerged = true;
3649 skinframe->qgeneratebase = skinframe->qhascolormapping;
3650 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3652 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3653 //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]);
3658 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3662 unsigned char *skindata;
3665 if (!skinframe->qpixels)
3668 if (!skinframe->qhascolormapping)
3669 colormapped = false;
3673 if (!skinframe->qgeneratebase)
3678 if (!skinframe->qgeneratemerged)
3682 width = skinframe->qwidth;
3683 height = skinframe->qheight;
3684 skindata = skinframe->qpixels;
3686 if (skinframe->qgeneratenmap)
3688 unsigned char *temp1, *temp2;
3689 skinframe->qgeneratenmap = false;
3690 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3691 temp2 = temp1 + width * height * 4;
3692 // use either a custom palette or the quake palette
3693 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3694 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3695 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3699 if (skinframe->qgenerateglow)
3701 skinframe->qgenerateglow = false;
3702 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3707 skinframe->qgeneratebase = false;
3708 skinframe->base = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3709 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3710 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3714 skinframe->qgeneratemerged = false;
3715 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);
3718 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3720 Mem_Free(skinframe->qpixels);
3721 skinframe->qpixels = NULL;
3725 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)
3728 skinframe_t *skinframe;
3731 if (cls.state == ca_dedicated)
3734 // if already loaded just return it, otherwise make a new skinframe
3735 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3736 if (skinframe->base)
3738 textureflags &= ~TEXF_FORCE_RELOAD;
3740 skinframe->stain = NULL;
3741 skinframe->merged = NULL;
3742 skinframe->base = NULL;
3743 skinframe->pants = NULL;
3744 skinframe->shirt = NULL;
3745 skinframe->nmap = NULL;
3746 skinframe->gloss = NULL;
3747 skinframe->glow = NULL;
3748 skinframe->fog = NULL;
3749 skinframe->reflect = NULL;
3750 skinframe->hasalpha = false;
3752 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3756 if (developer_loading.integer)
3757 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3759 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3760 if (textureflags & TEXF_ALPHA)
3762 for (i = 0;i < width * height;i++)
3764 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3766 skinframe->hasalpha = true;
3770 if (r_loadfog && skinframe->hasalpha)
3771 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3774 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3775 //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]);
3780 skinframe_t *R_SkinFrame_LoadMissing(void)
3782 skinframe_t *skinframe;
3784 if (cls.state == ca_dedicated)
3787 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3788 skinframe->stain = NULL;
3789 skinframe->merged = NULL;
3790 skinframe->base = NULL;
3791 skinframe->pants = NULL;
3792 skinframe->shirt = NULL;
3793 skinframe->nmap = NULL;
3794 skinframe->gloss = NULL;
3795 skinframe->glow = NULL;
3796 skinframe->fog = NULL;
3797 skinframe->reflect = NULL;
3798 skinframe->hasalpha = false;
3800 skinframe->avgcolor[0] = rand() / RAND_MAX;
3801 skinframe->avgcolor[1] = rand() / RAND_MAX;
3802 skinframe->avgcolor[2] = rand() / RAND_MAX;
3803 skinframe->avgcolor[3] = 1;
3808 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3809 typedef struct suffixinfo_s
3812 qboolean flipx, flipy, flipdiagonal;
3815 static suffixinfo_t suffix[3][6] =
3818 {"px", false, false, false},
3819 {"nx", false, false, false},
3820 {"py", false, false, false},
3821 {"ny", false, false, false},
3822 {"pz", false, false, false},
3823 {"nz", false, false, false}
3826 {"posx", false, false, false},
3827 {"negx", false, false, false},
3828 {"posy", false, false, false},
3829 {"negy", false, false, false},
3830 {"posz", false, false, false},
3831 {"negz", false, false, false}
3834 {"rt", true, false, true},
3835 {"lf", false, true, true},
3836 {"ft", true, true, false},
3837 {"bk", false, false, false},
3838 {"up", true, false, true},
3839 {"dn", true, false, true}
3843 static int componentorder[4] = {0, 1, 2, 3};
3845 static rtexture_t *R_LoadCubemap(const char *basename)
3847 int i, j, cubemapsize;
3848 unsigned char *cubemappixels, *image_buffer;
3849 rtexture_t *cubemaptexture;
3851 // must start 0 so the first loadimagepixels has no requested width/height
3853 cubemappixels = NULL;
3854 cubemaptexture = NULL;
3855 // keep trying different suffix groups (posx, px, rt) until one loads
3856 for (j = 0;j < 3 && !cubemappixels;j++)
3858 // load the 6 images in the suffix group
3859 for (i = 0;i < 6;i++)
3861 // generate an image name based on the base and and suffix
3862 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3864 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3866 // an image loaded, make sure width and height are equal
3867 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3869 // if this is the first image to load successfully, allocate the cubemap memory
3870 if (!cubemappixels && image_width >= 1)
3872 cubemapsize = image_width;
3873 // note this clears to black, so unavailable sides are black
3874 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3876 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3878 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);
3881 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3883 Mem_Free(image_buffer);
3887 // if a cubemap loaded, upload it
3890 if (developer_loading.integer)
3891 Con_Printf("loading cubemap \"%s\"\n", basename);
3893 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);
3894 Mem_Free(cubemappixels);
3898 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3899 if (developer_loading.integer)
3901 Con_Printf("(tried tried images ");
3902 for (j = 0;j < 3;j++)
3903 for (i = 0;i < 6;i++)
3904 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3905 Con_Print(" and was unable to find any of them).\n");
3908 return cubemaptexture;
3911 rtexture_t *R_GetCubemap(const char *basename)
3914 for (i = 0;i < r_texture_numcubemaps;i++)
3915 if (r_texture_cubemaps[i] != NULL)
3916 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3917 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3918 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3919 return r_texture_whitecube;
3920 r_texture_numcubemaps++;
3921 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3922 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3923 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3924 return r_texture_cubemaps[i]->texture;
3927 static void R_Main_FreeViewCache(void)
3929 if (r_refdef.viewcache.entityvisible)
3930 Mem_Free(r_refdef.viewcache.entityvisible);
3931 if (r_refdef.viewcache.world_pvsbits)
3932 Mem_Free(r_refdef.viewcache.world_pvsbits);
3933 if (r_refdef.viewcache.world_leafvisible)
3934 Mem_Free(r_refdef.viewcache.world_leafvisible);
3935 if (r_refdef.viewcache.world_surfacevisible)
3936 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3937 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3940 static void R_Main_ResizeViewCache(void)
3942 int numentities = r_refdef.scene.numentities;
3943 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3944 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3945 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3946 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3947 if (r_refdef.viewcache.maxentities < numentities)
3949 r_refdef.viewcache.maxentities = numentities;
3950 if (r_refdef.viewcache.entityvisible)
3951 Mem_Free(r_refdef.viewcache.entityvisible);
3952 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3954 if (r_refdef.viewcache.world_numclusters != numclusters)
3956 r_refdef.viewcache.world_numclusters = numclusters;
3957 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3958 if (r_refdef.viewcache.world_pvsbits)
3959 Mem_Free(r_refdef.viewcache.world_pvsbits);
3960 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3962 if (r_refdef.viewcache.world_numleafs != numleafs)
3964 r_refdef.viewcache.world_numleafs = numleafs;
3965 if (r_refdef.viewcache.world_leafvisible)
3966 Mem_Free(r_refdef.viewcache.world_leafvisible);
3967 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3969 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3971 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3972 if (r_refdef.viewcache.world_surfacevisible)
3973 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3974 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3978 extern rtexture_t *loadingscreentexture;
3979 static void gl_main_start(void)
3981 loadingscreentexture = NULL;
3982 r_texture_blanknormalmap = NULL;
3983 r_texture_white = NULL;
3984 r_texture_grey128 = NULL;
3985 r_texture_black = NULL;
3986 r_texture_whitecube = NULL;
3987 r_texture_normalizationcube = NULL;
3988 r_texture_fogattenuation = NULL;
3989 r_texture_fogheighttexture = NULL;
3990 r_texture_gammaramps = NULL;
3991 r_texture_numcubemaps = 0;
3992 r_uniformbufferalignment = 32;
3994 r_loaddds = r_texture_dds_load.integer != 0;
3995 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3997 switch(vid.renderpath)
3999 case RENDERPATH_GL20:
4000 case RENDERPATH_D3D9:
4001 case RENDERPATH_D3D10:
4002 case RENDERPATH_D3D11:
4003 case RENDERPATH_SOFT:
4004 case RENDERPATH_GLES2:
4005 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4006 Cvar_SetValueQuick(&gl_combine, 1);
4007 Cvar_SetValueQuick(&r_glsl, 1);
4008 r_loadnormalmap = true;
4011 if (vid.support.arb_uniform_buffer_object)
4012 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4014 case RENDERPATH_GL13:
4015 case RENDERPATH_GLES1:
4016 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4017 Cvar_SetValueQuick(&gl_combine, 1);
4018 Cvar_SetValueQuick(&r_glsl, 0);
4019 r_loadnormalmap = false;
4020 r_loadgloss = false;
4023 case RENDERPATH_GL11:
4024 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4025 Cvar_SetValueQuick(&gl_combine, 0);
4026 Cvar_SetValueQuick(&r_glsl, 0);
4027 r_loadnormalmap = false;
4028 r_loadgloss = false;
4034 R_FrameData_Reset();
4035 R_BufferData_Reset();
4039 memset(r_queries, 0, sizeof(r_queries));
4041 r_qwskincache = NULL;
4042 r_qwskincache_size = 0;
4044 // due to caching of texture_t references, the collision cache must be reset
4045 Collision_Cache_Reset(true);
4047 // set up r_skinframe loading system for textures
4048 memset(&r_skinframe, 0, sizeof(r_skinframe));
4049 r_skinframe.loadsequence = 1;
4050 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4052 r_main_texturepool = R_AllocTexturePool();
4053 R_BuildBlankTextures();
4055 if (vid.support.arb_texture_cube_map)
4058 R_BuildNormalizationCube();
4060 r_texture_fogattenuation = NULL;
4061 r_texture_fogheighttexture = NULL;
4062 r_texture_gammaramps = NULL;
4063 //r_texture_fogintensity = NULL;
4064 memset(&r_fb, 0, sizeof(r_fb));
4065 r_glsl_permutation = NULL;
4066 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4067 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4068 glslshaderstring = NULL;
4070 r_hlsl_permutation = NULL;
4071 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4072 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4074 hlslshaderstring = NULL;
4075 memset(&r_svbsp, 0, sizeof (r_svbsp));
4077 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4078 r_texture_numcubemaps = 0;
4080 r_refdef.fogmasktable_density = 0;
4083 static void gl_main_shutdown(void)
4086 R_FrameData_Reset();
4087 R_BufferData_Reset();
4089 R_Main_FreeViewCache();
4091 switch(vid.renderpath)
4093 case RENDERPATH_GL11:
4094 case RENDERPATH_GL13:
4095 case RENDERPATH_GL20:
4096 case RENDERPATH_GLES1:
4097 case RENDERPATH_GLES2:
4098 #ifdef GL_SAMPLES_PASSED_ARB
4100 qglDeleteQueriesARB(r_maxqueries, r_queries);
4103 case RENDERPATH_D3D9:
4104 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4106 case RENDERPATH_D3D10:
4107 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4109 case RENDERPATH_D3D11:
4110 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4112 case RENDERPATH_SOFT:
4118 memset(r_queries, 0, sizeof(r_queries));
4120 r_qwskincache = NULL;
4121 r_qwskincache_size = 0;
4123 // clear out the r_skinframe state
4124 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4125 memset(&r_skinframe, 0, sizeof(r_skinframe));
4128 Mem_Free(r_svbsp.nodes);
4129 memset(&r_svbsp, 0, sizeof (r_svbsp));
4130 R_FreeTexturePool(&r_main_texturepool);
4131 loadingscreentexture = NULL;
4132 r_texture_blanknormalmap = NULL;
4133 r_texture_white = NULL;
4134 r_texture_grey128 = NULL;
4135 r_texture_black = NULL;
4136 r_texture_whitecube = NULL;
4137 r_texture_normalizationcube = NULL;
4138 r_texture_fogattenuation = NULL;
4139 r_texture_fogheighttexture = NULL;
4140 r_texture_gammaramps = NULL;
4141 r_texture_numcubemaps = 0;
4142 //r_texture_fogintensity = NULL;
4143 memset(&r_fb, 0, sizeof(r_fb));
4146 r_glsl_permutation = NULL;
4147 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4148 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4149 glslshaderstring = NULL;
4151 r_hlsl_permutation = NULL;
4152 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4153 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4155 hlslshaderstring = NULL;
4158 static void gl_main_newmap(void)
4160 // FIXME: move this code to client
4161 char *entities, entname[MAX_QPATH];
4163 Mem_Free(r_qwskincache);
4164 r_qwskincache = NULL;
4165 r_qwskincache_size = 0;
4168 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4169 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4171 CL_ParseEntityLump(entities);
4175 if (cl.worldmodel->brush.entities)
4176 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4178 R_Main_FreeViewCache();
4180 R_FrameData_Reset();
4181 R_BufferData_Reset();
4184 void GL_Main_Init(void)
4187 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4189 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4190 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4191 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4192 if (gamemode == GAME_NEHAHRA)
4194 Cvar_RegisterVariable (&gl_fogenable);
4195 Cvar_RegisterVariable (&gl_fogdensity);
4196 Cvar_RegisterVariable (&gl_fogred);
4197 Cvar_RegisterVariable (&gl_foggreen);
4198 Cvar_RegisterVariable (&gl_fogblue);
4199 Cvar_RegisterVariable (&gl_fogstart);
4200 Cvar_RegisterVariable (&gl_fogend);
4201 Cvar_RegisterVariable (&gl_skyclip);
4203 Cvar_RegisterVariable(&r_motionblur);
4204 Cvar_RegisterVariable(&r_damageblur);
4205 Cvar_RegisterVariable(&r_motionblur_averaging);
4206 Cvar_RegisterVariable(&r_motionblur_randomize);
4207 Cvar_RegisterVariable(&r_motionblur_minblur);
4208 Cvar_RegisterVariable(&r_motionblur_maxblur);
4209 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4210 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4211 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4212 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4213 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4214 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4215 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4216 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4217 Cvar_RegisterVariable(&r_equalize_entities_by);
4218 Cvar_RegisterVariable(&r_equalize_entities_to);
4219 Cvar_RegisterVariable(&r_depthfirst);
4220 Cvar_RegisterVariable(&r_useinfinitefarclip);
4221 Cvar_RegisterVariable(&r_farclip_base);
4222 Cvar_RegisterVariable(&r_farclip_world);
4223 Cvar_RegisterVariable(&r_nearclip);
4224 Cvar_RegisterVariable(&r_deformvertexes);
4225 Cvar_RegisterVariable(&r_transparent);
4226 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4227 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4228 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4229 Cvar_RegisterVariable(&r_showoverdraw);
4230 Cvar_RegisterVariable(&r_showbboxes);
4231 Cvar_RegisterVariable(&r_showsurfaces);
4232 Cvar_RegisterVariable(&r_showtris);
4233 Cvar_RegisterVariable(&r_shownormals);
4234 Cvar_RegisterVariable(&r_showlighting);
4235 Cvar_RegisterVariable(&r_showshadowvolumes);
4236 Cvar_RegisterVariable(&r_showcollisionbrushes);
4237 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4238 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4239 Cvar_RegisterVariable(&r_showdisabledepthtest);
4240 Cvar_RegisterVariable(&r_drawportals);
4241 Cvar_RegisterVariable(&r_drawentities);
4242 Cvar_RegisterVariable(&r_draw2d);
4243 Cvar_RegisterVariable(&r_drawworld);
4244 Cvar_RegisterVariable(&r_cullentities_trace);
4245 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4246 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4247 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4248 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4249 Cvar_RegisterVariable(&r_sortentities);
4250 Cvar_RegisterVariable(&r_drawviewmodel);
4251 Cvar_RegisterVariable(&r_drawexteriormodel);
4252 Cvar_RegisterVariable(&r_speeds);
4253 Cvar_RegisterVariable(&r_fullbrights);
4254 Cvar_RegisterVariable(&r_wateralpha);
4255 Cvar_RegisterVariable(&r_dynamic);
4256 Cvar_RegisterVariable(&r_fakelight);
4257 Cvar_RegisterVariable(&r_fakelight_intensity);
4258 Cvar_RegisterVariable(&r_fullbright);
4259 Cvar_RegisterVariable(&r_shadows);
4260 Cvar_RegisterVariable(&r_shadows_darken);
4261 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4262 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4263 Cvar_RegisterVariable(&r_shadows_throwdistance);
4264 Cvar_RegisterVariable(&r_shadows_throwdirection);
4265 Cvar_RegisterVariable(&r_shadows_focus);
4266 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4267 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4268 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4269 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4270 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4271 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4272 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4273 Cvar_RegisterVariable(&r_fog_exp2);
4274 Cvar_RegisterVariable(&r_fog_clear);
4275 Cvar_RegisterVariable(&r_drawfog);
4276 Cvar_RegisterVariable(&r_transparentdepthmasking);
4277 Cvar_RegisterVariable(&r_transparent_sortmindist);
4278 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4279 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4280 Cvar_RegisterVariable(&r_texture_dds_load);
4281 Cvar_RegisterVariable(&r_texture_dds_save);
4282 Cvar_RegisterVariable(&r_textureunits);
4283 Cvar_RegisterVariable(&gl_combine);
4284 Cvar_RegisterVariable(&r_usedepthtextures);
4285 Cvar_RegisterVariable(&r_viewfbo);
4286 Cvar_RegisterVariable(&r_viewscale);
4287 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4288 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4289 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4290 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4291 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4292 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4293 Cvar_RegisterVariable(&r_glsl);
4294 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4295 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4296 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4297 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4298 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4299 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4300 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4301 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4302 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4303 Cvar_RegisterVariable(&r_glsl_postprocess);
4304 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4305 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4306 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4307 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4308 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4309 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4310 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4311 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4312 Cvar_RegisterVariable(&r_celshading);
4313 Cvar_RegisterVariable(&r_celoutlines);
4315 Cvar_RegisterVariable(&r_water);
4316 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4317 Cvar_RegisterVariable(&r_water_clippingplanebias);
4318 Cvar_RegisterVariable(&r_water_refractdistort);
4319 Cvar_RegisterVariable(&r_water_reflectdistort);
4320 Cvar_RegisterVariable(&r_water_scissormode);
4321 Cvar_RegisterVariable(&r_water_lowquality);
4322 Cvar_RegisterVariable(&r_water_hideplayer);
4323 Cvar_RegisterVariable(&r_water_fbo);
4325 Cvar_RegisterVariable(&r_lerpsprites);
4326 Cvar_RegisterVariable(&r_lerpmodels);
4327 Cvar_RegisterVariable(&r_lerplightstyles);
4328 Cvar_RegisterVariable(&r_waterscroll);
4329 Cvar_RegisterVariable(&r_bloom);
4330 Cvar_RegisterVariable(&r_bloom_colorscale);
4331 Cvar_RegisterVariable(&r_bloom_brighten);
4332 Cvar_RegisterVariable(&r_bloom_blur);
4333 Cvar_RegisterVariable(&r_bloom_resolution);
4334 Cvar_RegisterVariable(&r_bloom_colorexponent);
4335 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4336 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4337 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4338 Cvar_RegisterVariable(&r_hdr_glowintensity);
4339 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4340 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4341 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4342 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4343 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4344 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4345 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4346 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4347 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4348 Cvar_RegisterVariable(&developer_texturelogging);
4349 Cvar_RegisterVariable(&gl_lightmaps);
4350 Cvar_RegisterVariable(&r_test);
4351 Cvar_RegisterVariable(&r_batch_multidraw);
4352 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4353 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4354 Cvar_RegisterVariable(&r_glsl_skeletal);
4355 Cvar_RegisterVariable(&r_glsl_saturation);
4356 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4357 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4358 Cvar_RegisterVariable(&r_framedatasize);
4359 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4360 Cvar_RegisterVariable(&r_buffermegs[i]);
4361 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4362 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4363 Cvar_SetValue("r_fullbrights", 0);
4364 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4367 void Render_Init(void)
4380 R_LightningBeams_Init();
4390 extern char *ENGINE_EXTENSIONS;
4393 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4394 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4395 gl_version = (const char *)qglGetString(GL_VERSION);
4396 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4400 if (!gl_platformextensions)
4401 gl_platformextensions = "";
4403 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4404 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4405 Con_Printf("GL_VERSION: %s\n", gl_version);
4406 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4407 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4409 VID_CheckExtensions();
4411 // LordHavoc: report supported extensions
4412 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4414 // clear to black (loading plaque will be seen over this)
4415 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4419 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4423 if (r_trippy.integer)
4425 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4427 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4430 p = r_refdef.view.frustum + i;
4435 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4439 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4443 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4447 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4451 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4455 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4459 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4463 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4471 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4475 if (r_trippy.integer)
4477 for (i = 0;i < numplanes;i++)
4484 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4488 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4492 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4496 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4500 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4504 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4508 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4512 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4520 //==================================================================================
4522 // LordHavoc: this stores temporary data used within the same frame
4524 typedef struct r_framedata_mem_s
4526 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4527 size_t size; // how much usable space
4528 size_t current; // how much space in use
4529 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4530 size_t wantedsize; // how much space was allocated
4531 unsigned char *data; // start of real data (16byte aligned)
4535 static r_framedata_mem_t *r_framedata_mem;
4537 void R_FrameData_Reset(void)
4539 while (r_framedata_mem)
4541 r_framedata_mem_t *next = r_framedata_mem->purge;
4542 Mem_Free(r_framedata_mem);
4543 r_framedata_mem = next;
4547 static void R_FrameData_Resize(qboolean mustgrow)
4550 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4551 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4552 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4554 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4555 newmem->wantedsize = wantedsize;
4556 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4557 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4558 newmem->current = 0;
4560 newmem->purge = r_framedata_mem;
4561 r_framedata_mem = newmem;
4565 void R_FrameData_NewFrame(void)
4567 R_FrameData_Resize(false);
4568 if (!r_framedata_mem)
4570 // if we ran out of space on the last frame, free the old memory now
4571 while (r_framedata_mem->purge)
4573 // repeatedly remove the second item in the list, leaving only head
4574 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4575 Mem_Free(r_framedata_mem->purge);
4576 r_framedata_mem->purge = next;
4578 // reset the current mem pointer
4579 r_framedata_mem->current = 0;
4580 r_framedata_mem->mark = 0;
4583 void *R_FrameData_Alloc(size_t size)
4588 // align to 16 byte boundary - the data pointer is already aligned, so we
4589 // only need to ensure the size of every allocation is also aligned
4590 size = (size + 15) & ~15;
4592 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4594 // emergency - we ran out of space, allocate more memory
4595 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4596 // this might not be a growing it, but we'll allocate another buffer every time
4597 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4598 R_FrameData_Resize(true);
4601 data = r_framedata_mem->data + r_framedata_mem->current;
4602 r_framedata_mem->current += size;
4604 // count the usage for stats
4605 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4606 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4608 return (void *)data;
4611 void *R_FrameData_Store(size_t size, void *data)
4613 void *d = R_FrameData_Alloc(size);
4615 memcpy(d, data, size);
4619 void R_FrameData_SetMark(void)
4621 if (!r_framedata_mem)
4623 r_framedata_mem->mark = r_framedata_mem->current;
4626 void R_FrameData_ReturnToMark(void)
4628 if (!r_framedata_mem)
4630 r_framedata_mem->current = r_framedata_mem->mark;
4633 //==================================================================================
4635 // avoid reusing the same buffer objects on consecutive frames
4636 #define R_BUFFERDATA_CYCLE 3
4638 typedef struct r_bufferdata_buffer_s
4640 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4641 size_t size; // how much usable space
4642 size_t current; // how much space in use
4643 r_meshbuffer_t *buffer; // the buffer itself
4645 r_bufferdata_buffer_t;
4647 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4648 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4650 /// frees all dynamic buffers
4651 void R_BufferData_Reset(void)
4654 r_bufferdata_buffer_t **p, *mem;
4655 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4657 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4660 p = &r_bufferdata_buffer[cycle][type];
4666 R_Mesh_DestroyMeshBuffer(mem->buffer);
4673 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4674 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4676 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4678 float newvalue = r_buffermegs[type].value;
4680 // increase the cvar if we have to (but only if we already have a mem)
4681 if (mustgrow && mem)
4683 newvalue = bound(0.25f, newvalue, 256.0f);
4684 while (newvalue * 1024*1024 < minsize)
4687 // clamp the cvar to valid range
4688 newvalue = bound(0.25f, newvalue, 256.0f);
4689 if (r_buffermegs[type].value != newvalue)
4690 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4692 // calculate size in bytes
4693 size = (size_t)(newvalue * 1024*1024);
4694 size = bound(131072, size, 256*1024*1024);
4696 // allocate a new buffer if the size is different (purge old one later)
4697 // or if we were told we must grow the buffer
4698 if (!mem || mem->size != size || mustgrow)
4700 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4703 if (type == R_BUFFERDATA_VERTEX)
4704 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4705 else if (type == R_BUFFERDATA_INDEX16)
4706 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4707 else if (type == R_BUFFERDATA_INDEX32)
4708 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4709 else if (type == R_BUFFERDATA_UNIFORM)
4710 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4711 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4712 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4716 void R_BufferData_NewFrame(void)
4719 r_bufferdata_buffer_t **p, *mem;
4720 // cycle to the next frame's buffers
4721 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4722 // if we ran out of space on the last time we used these buffers, free the old memory now
4723 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4725 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4727 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4728 // free all but the head buffer, this is how we recycle obsolete
4729 // buffers after they are no longer in use
4730 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4736 R_Mesh_DestroyMeshBuffer(mem->buffer);
4739 // reset the current offset
4740 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4745 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4747 r_bufferdata_buffer_t *mem;
4751 *returnbufferoffset = 0;
4753 // align size to a byte boundary appropriate for the buffer type, this
4754 // makes all allocations have aligned start offsets
4755 if (type == R_BUFFERDATA_UNIFORM)
4756 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4758 padsize = (datasize + 15) & ~15;
4760 // if we ran out of space in this buffer we must allocate a new one
4761 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4762 R_BufferData_Resize(type, true, padsize);
4764 // if the resize did not give us enough memory, fail
4765 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4766 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4768 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4769 offset = mem->current;
4770 mem->current += padsize;
4772 // upload the data to the buffer at the chosen offset
4774 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4775 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4777 // count the usage for stats
4778 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4779 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4781 // return the buffer offset
4782 *returnbufferoffset = offset;
4787 //==================================================================================
4789 // LordHavoc: animcache originally written by Echon, rewritten since then
4792 * Animation cache prevents re-generating mesh data for an animated model
4793 * multiple times in one frame for lighting, shadowing, reflections, etc.
4796 void R_AnimCache_Free(void)
4800 void R_AnimCache_ClearCache(void)
4803 entity_render_t *ent;
4805 for (i = 0;i < r_refdef.scene.numentities;i++)
4807 ent = r_refdef.scene.entities[i];
4808 ent->animcache_vertex3f = NULL;
4809 ent->animcache_vertex3f_vertexbuffer = NULL;
4810 ent->animcache_vertex3f_bufferoffset = 0;
4811 ent->animcache_normal3f = NULL;
4812 ent->animcache_normal3f_vertexbuffer = NULL;
4813 ent->animcache_normal3f_bufferoffset = 0;
4814 ent->animcache_svector3f = NULL;
4815 ent->animcache_svector3f_vertexbuffer = NULL;
4816 ent->animcache_svector3f_bufferoffset = 0;
4817 ent->animcache_tvector3f = NULL;
4818 ent->animcache_tvector3f_vertexbuffer = NULL;
4819 ent->animcache_tvector3f_bufferoffset = 0;
4820 ent->animcache_vertexmesh = NULL;
4821 ent->animcache_vertexmesh_vertexbuffer = NULL;
4822 ent->animcache_vertexmesh_bufferoffset = 0;
4823 ent->animcache_skeletaltransform3x4 = NULL;
4824 ent->animcache_skeletaltransform3x4buffer = NULL;
4825 ent->animcache_skeletaltransform3x4offset = 0;
4826 ent->animcache_skeletaltransform3x4size = 0;
4830 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4834 // check if we need the meshbuffers
4835 if (!vid.useinterleavedarrays)
4838 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4839 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4840 // TODO: upload vertexbuffer?
4841 if (ent->animcache_vertexmesh)
4843 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4844 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4845 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4846 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4847 for (i = 0;i < numvertices;i++)
4848 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4849 if (ent->animcache_svector3f)
4850 for (i = 0;i < numvertices;i++)
4851 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4852 if (ent->animcache_tvector3f)
4853 for (i = 0;i < numvertices;i++)
4854 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4855 if (ent->animcache_normal3f)
4856 for (i = 0;i < numvertices;i++)
4857 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4861 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4863 dp_model_t *model = ent->model;
4866 // see if this ent is worth caching
4867 if (!model || !model->Draw || !model->AnimateVertices)
4869 // nothing to cache if it contains no animations and has no skeleton
4870 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4872 // see if it is already cached for gpuskeletal
4873 if (ent->animcache_skeletaltransform3x4)
4875 // see if it is already cached as a mesh
4876 if (ent->animcache_vertex3f)
4878 // check if we need to add normals or tangents
4879 if (ent->animcache_normal3f)
4880 wantnormals = false;
4881 if (ent->animcache_svector3f)
4882 wanttangents = false;
4883 if (!wantnormals && !wanttangents)
4887 // check which kind of cache we need to generate
4888 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4890 // cache the skeleton so the vertex shader can use it
4891 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4892 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4893 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4894 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4895 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4896 // note: this can fail if the buffer is at the grow limit
4897 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4898 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4900 else if (ent->animcache_vertex3f)
4902 // mesh was already cached but we may need to add normals/tangents
4903 // (this only happens with multiple views, reflections, cameras, etc)
4904 if (wantnormals || wanttangents)
4906 numvertices = model->surfmesh.num_vertices;
4908 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4911 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4912 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4914 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4915 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4916 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4917 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4918 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4923 // generate mesh cache
4924 numvertices = model->surfmesh.num_vertices;
4925 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4927 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4930 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4931 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4933 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4934 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4935 if (wantnormals || wanttangents)
4937 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4938 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4939 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4941 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4942 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4943 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4948 void R_AnimCache_CacheVisibleEntities(void)
4951 qboolean wantnormals = true;
4952 qboolean wanttangents = !r_showsurfaces.integer;
4954 switch(vid.renderpath)
4956 case RENDERPATH_GL20:
4957 case RENDERPATH_D3D9:
4958 case RENDERPATH_D3D10:
4959 case RENDERPATH_D3D11:
4960 case RENDERPATH_GLES2:
4962 case RENDERPATH_GL11:
4963 case RENDERPATH_GL13:
4964 case RENDERPATH_GLES1:
4965 wanttangents = false;
4967 case RENDERPATH_SOFT:
4971 if (r_shownormals.integer)
4972 wanttangents = wantnormals = true;
4974 // TODO: thread this
4975 // NOTE: R_PrepareRTLights() also caches entities
4977 for (i = 0;i < r_refdef.scene.numentities;i++)
4978 if (r_refdef.viewcache.entityvisible[i])
4979 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4982 //==================================================================================
4984 extern cvar_t r_overheadsprites_pushback;
4986 static void R_View_UpdateEntityLighting (void)
4989 entity_render_t *ent;
4990 vec3_t tempdiffusenormal, avg;
4991 vec_t f, fa, fd, fdd;
4992 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4994 for (i = 0;i < r_refdef.scene.numentities;i++)
4996 ent = r_refdef.scene.entities[i];
4998 // skip unseen models
4999 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5003 if (ent->model && ent->model == cl.worldmodel)
5005 // TODO: use modellight for r_ambient settings on world?
5006 VectorSet(ent->modellight_ambient, 0, 0, 0);
5007 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5008 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5012 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5014 // aleady updated by CSQC
5015 // TODO: force modellight on BSP models in this case?
5016 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5020 // fetch the lighting from the worldmodel data
5021 VectorClear(ent->modellight_ambient);
5022 VectorClear(ent->modellight_diffuse);
5023 VectorClear(tempdiffusenormal);
5024 if (ent->flags & RENDER_LIGHT)
5027 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5029 // complete lightning for lit sprites
5030 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5031 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5033 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5034 org[2] = org[2] + r_overheadsprites_pushback.value;
5035 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5038 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5040 if(ent->flags & RENDER_EQUALIZE)
5042 // first fix up ambient lighting...
5043 if(r_equalize_entities_minambient.value > 0)
5045 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5048 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5049 if(fa < r_equalize_entities_minambient.value * fd)
5052 // fa'/fd' = minambient
5053 // fa'+0.25*fd' = fa+0.25*fd
5055 // fa' = fd' * minambient
5056 // fd'*(0.25+minambient) = fa+0.25*fd
5058 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5059 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5061 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5062 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
5063 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5064 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5069 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5071 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5072 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5076 // adjust brightness and saturation to target
5077 avg[0] = avg[1] = avg[2] = fa / f;
5078 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5079 avg[0] = avg[1] = avg[2] = fd / f;
5080 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5086 VectorSet(ent->modellight_ambient, 1, 1, 1);
5089 // move the light direction into modelspace coordinates for lighting code
5090 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5091 if(VectorLength2(ent->modellight_lightdir) == 0)
5092 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5093 VectorNormalize(ent->modellight_lightdir);
5097 #define MAX_LINEOFSIGHTTRACES 64
5099 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5102 vec3_t boxmins, boxmaxs;
5105 dp_model_t *model = r_refdef.scene.worldmodel;
5107 if (!model || !model->brush.TraceLineOfSight)
5110 // expand the box a little
5111 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5112 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5113 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5114 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5115 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5116 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5118 // return true if eye is inside enlarged box
5119 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5123 VectorCopy(eye, start);
5124 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5125 if (model->brush.TraceLineOfSight(model, start, end))
5128 // try various random positions
5129 for (i = 0;i < numsamples;i++)
5131 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5132 if (model->brush.TraceLineOfSight(model, start, end))
5140 static void R_View_UpdateEntityVisible (void)
5145 entity_render_t *ent;
5147 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5148 : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5149 : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL
5150 : RENDER_EXTERIORMODEL;
5151 if (!r_drawviewmodel.integer)
5152 renderimask |= RENDER_VIEWMODEL;
5153 if (!r_drawexteriormodel.integer)
5154 renderimask |= RENDER_EXTERIORMODEL;
5155 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5157 // worldmodel can check visibility
5158 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5159 for (i = 0;i < r_refdef.scene.numentities;i++)
5161 ent = r_refdef.scene.entities[i];
5162 if (!(ent->flags & renderimask))
5163 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)))
5164 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
5165 r_refdef.viewcache.entityvisible[i] = true;
5170 // no worldmodel or it can't check visibility
5171 for (i = 0;i < r_refdef.scene.numentities;i++)
5173 ent = r_refdef.scene.entities[i];
5174 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));
5177 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5178 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5180 for (i = 0;i < r_refdef.scene.numentities;i++)
5182 if (!r_refdef.viewcache.entityvisible[i])
5184 ent = r_refdef.scene.entities[i];
5185 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5187 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5189 continue; // temp entities do pvs only
5190 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5191 ent->last_trace_visibility = realtime;
5192 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5193 r_refdef.viewcache.entityvisible[i] = 0;
5199 /// only used if skyrendermasked, and normally returns false
5200 static int R_DrawBrushModelsSky (void)
5203 entity_render_t *ent;
5206 for (i = 0;i < r_refdef.scene.numentities;i++)
5208 if (!r_refdef.viewcache.entityvisible[i])
5210 ent = r_refdef.scene.entities[i];
5211 if (!ent->model || !ent->model->DrawSky)
5213 ent->model->DrawSky(ent);
5219 static void R_DrawNoModel(entity_render_t *ent);
5220 static void R_DrawModels(void)
5223 entity_render_t *ent;
5225 for (i = 0;i < r_refdef.scene.numentities;i++)
5227 if (!r_refdef.viewcache.entityvisible[i])
5229 ent = r_refdef.scene.entities[i];
5230 r_refdef.stats[r_stat_entities]++;
5232 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5235 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5236 Con_Printf("R_DrawModels\n");
5237 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]);
5238 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);
5239 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);
5242 if (ent->model && ent->model->Draw != NULL)
5243 ent->model->Draw(ent);
5249 static void R_DrawModelsDepth(void)
5252 entity_render_t *ent;
5254 for (i = 0;i < r_refdef.scene.numentities;i++)
5256 if (!r_refdef.viewcache.entityvisible[i])
5258 ent = r_refdef.scene.entities[i];
5259 if (ent->model && ent->model->DrawDepth != NULL)
5260 ent->model->DrawDepth(ent);
5264 static void R_DrawModelsDebug(void)
5267 entity_render_t *ent;
5269 for (i = 0;i < r_refdef.scene.numentities;i++)
5271 if (!r_refdef.viewcache.entityvisible[i])
5273 ent = r_refdef.scene.entities[i];
5274 if (ent->model && ent->model->DrawDebug != NULL)
5275 ent->model->DrawDebug(ent);
5279 static void R_DrawModelsAddWaterPlanes(void)
5282 entity_render_t *ent;
5284 for (i = 0;i < r_refdef.scene.numentities;i++)
5286 if (!r_refdef.viewcache.entityvisible[i])
5288 ent = r_refdef.scene.entities[i];
5289 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5290 ent->model->DrawAddWaterPlanes(ent);
5294 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5296 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5298 if (r_hdr_irisadaptation.integer)
5303 vec3_t diffusenormal;
5305 vec_t brightness = 0.0f;
5310 VectorCopy(r_refdef.view.forward, forward);
5311 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5313 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5314 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5315 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5316 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5317 d = DotProduct(forward, diffusenormal);
5318 brightness += VectorLength(ambient);
5320 brightness += d * VectorLength(diffuse);
5322 brightness *= 1.0f / c;
5323 brightness += 0.00001f; // make sure it's never zero
5324 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5325 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5326 current = r_hdr_irisadaptation_value.value;
5328 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5329 else if (current > goal)
5330 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5331 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5332 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5334 else if (r_hdr_irisadaptation_value.value != 1.0f)
5335 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5338 static void R_View_SetFrustum(const int *scissor)
5341 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5342 vec3_t forward, left, up, origin, v;
5346 // flipped x coordinates (because x points left here)
5347 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5348 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5350 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5351 switch(vid.renderpath)
5353 case RENDERPATH_D3D9:
5354 case RENDERPATH_D3D10:
5355 case RENDERPATH_D3D11:
5356 // non-flipped y coordinates
5357 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5358 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5360 case RENDERPATH_SOFT:
5361 case RENDERPATH_GL11:
5362 case RENDERPATH_GL13:
5363 case RENDERPATH_GL20:
5364 case RENDERPATH_GLES1:
5365 case RENDERPATH_GLES2:
5366 // non-flipped y coordinates
5367 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5368 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5373 // we can't trust r_refdef.view.forward and friends in reflected scenes
5374 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5377 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5378 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5379 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5380 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5381 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5382 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5383 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5384 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5385 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5386 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5387 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5388 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5392 zNear = r_refdef.nearclip;
5393 nudge = 1.0 - 1.0 / (1<<23);
5394 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5395 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5396 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5397 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5398 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5399 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5400 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5401 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5407 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5408 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5409 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5410 r_refdef.view.frustum[0].dist = m[15] - m[12];
5412 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5413 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5414 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5415 r_refdef.view.frustum[1].dist = m[15] + m[12];
5417 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5418 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5419 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5420 r_refdef.view.frustum[2].dist = m[15] - m[13];
5422 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5423 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5424 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5425 r_refdef.view.frustum[3].dist = m[15] + m[13];
5427 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5428 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5429 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5430 r_refdef.view.frustum[4].dist = m[15] - m[14];
5432 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5433 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5434 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5435 r_refdef.view.frustum[5].dist = m[15] + m[14];
5438 if (r_refdef.view.useperspective)
5440 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5441 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]);
5442 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]);
5443 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]);
5444 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]);
5446 // then the normals from the corners relative to origin
5447 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5448 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5449 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5450 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5452 // in a NORMAL view, forward cross left == up
5453 // in a REFLECTED view, forward cross left == down
5454 // so our cross products above need to be adjusted for a left handed coordinate system
5455 CrossProduct(forward, left, v);
5456 if(DotProduct(v, up) < 0)
5458 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5459 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5460 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5461 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5464 // Leaving those out was a mistake, those were in the old code, and they
5465 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5466 // I couldn't reproduce it after adding those normalizations. --blub
5467 VectorNormalize(r_refdef.view.frustum[0].normal);
5468 VectorNormalize(r_refdef.view.frustum[1].normal);
5469 VectorNormalize(r_refdef.view.frustum[2].normal);
5470 VectorNormalize(r_refdef.view.frustum[3].normal);
5472 // make the corners absolute
5473 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5474 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5475 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5476 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5479 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5481 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5482 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5483 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5484 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5485 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5489 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5490 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5491 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5492 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5493 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5494 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5495 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5496 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5497 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5498 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5500 r_refdef.view.numfrustumplanes = 5;
5502 if (r_refdef.view.useclipplane)
5504 r_refdef.view.numfrustumplanes = 6;
5505 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5508 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5509 PlaneClassify(r_refdef.view.frustum + i);
5511 // LordHavoc: note to all quake engine coders, Quake had a special case
5512 // for 90 degrees which assumed a square view (wrong), so I removed it,
5513 // Quake2 has it disabled as well.
5515 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5516 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5517 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5518 //PlaneClassify(&frustum[0]);
5520 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5521 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5522 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5523 //PlaneClassify(&frustum[1]);
5525 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5526 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5527 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5528 //PlaneClassify(&frustum[2]);
5530 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5531 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5532 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5533 //PlaneClassify(&frustum[3]);
5536 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5537 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5538 //PlaneClassify(&frustum[4]);
5541 static void R_View_UpdateWithScissor(const int *myscissor)
5543 R_Main_ResizeViewCache();
5544 R_View_SetFrustum(myscissor);
5545 R_View_WorldVisibility(r_refdef.view.useclipplane);
5546 R_View_UpdateEntityVisible();
5547 R_View_UpdateEntityLighting();
5550 static void R_View_Update(void)
5552 R_Main_ResizeViewCache();
5553 R_View_SetFrustum(NULL);
5554 R_View_WorldVisibility(r_refdef.view.useclipplane);
5555 R_View_UpdateEntityVisible();
5556 R_View_UpdateEntityLighting();
5559 float viewscalefpsadjusted = 1.0f;
5561 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5563 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5564 scale = bound(0.03125f, scale, 1.0f);
5565 *outwidth = (int)ceil(width * scale);
5566 *outheight = (int)ceil(height * scale);
5569 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5571 const float *customclipplane = NULL;
5573 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5574 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5576 // LordHavoc: couldn't figure out how to make this approach the
5577 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5578 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5579 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5580 dist = r_refdef.view.clipplane.dist;
5581 plane[0] = r_refdef.view.clipplane.normal[0];
5582 plane[1] = r_refdef.view.clipplane.normal[1];
5583 plane[2] = r_refdef.view.clipplane.normal[2];
5585 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5588 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5589 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5591 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5592 if (!r_refdef.view.useperspective)
5593 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - 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);
5594 else if (vid.stencil && r_useinfinitefarclip.integer)
5595 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5597 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5598 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5599 R_SetViewport(&r_refdef.view.viewport);
5600 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5602 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5603 float screenplane[4];
5604 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5605 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5606 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5607 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5608 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5612 void R_EntityMatrix(const matrix4x4_t *matrix)
5614 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5616 gl_modelmatrixchanged = false;
5617 gl_modelmatrix = *matrix;
5618 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5619 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5620 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5621 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5623 switch(vid.renderpath)
5625 case RENDERPATH_D3D9:
5627 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5628 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5631 case RENDERPATH_D3D10:
5632 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5634 case RENDERPATH_D3D11:
5635 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5637 case RENDERPATH_GL11:
5638 case RENDERPATH_GL13:
5639 case RENDERPATH_GLES1:
5640 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5642 case RENDERPATH_SOFT:
5643 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5644 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5646 case RENDERPATH_GL20:
5647 case RENDERPATH_GLES2:
5648 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5649 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5655 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5657 r_viewport_t viewport;
5661 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5662 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, x2, y2, -10, 100, NULL);
5663 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5664 R_SetViewport(&viewport);
5665 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5666 GL_Color(1, 1, 1, 1);
5667 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5668 GL_BlendFunc(GL_ONE, GL_ZERO);
5669 GL_ScissorTest(false);
5670 GL_DepthMask(false);
5671 GL_DepthRange(0, 1);
5672 GL_DepthTest(false);
5673 GL_DepthFunc(GL_LEQUAL);
5674 R_EntityMatrix(&identitymatrix);
5675 R_Mesh_ResetTextureState();
5676 GL_PolygonOffset(0, 0);
5677 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5678 switch(vid.renderpath)
5680 case RENDERPATH_GL11:
5681 case RENDERPATH_GL13:
5682 case RENDERPATH_GL20:
5683 case RENDERPATH_GLES1:
5684 case RENDERPATH_GLES2:
5685 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5687 case RENDERPATH_D3D9:
5688 case RENDERPATH_D3D10:
5689 case RENDERPATH_D3D11:
5690 case RENDERPATH_SOFT:
5693 GL_CullFace(GL_NONE);
5698 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5702 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5705 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5709 R_SetupView(true, fbo, depthtexture, colortexture);
5710 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5711 GL_Color(1, 1, 1, 1);
5712 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5713 GL_BlendFunc(GL_ONE, GL_ZERO);
5714 GL_ScissorTest(true);
5716 GL_DepthRange(0, 1);
5718 GL_DepthFunc(GL_LEQUAL);
5719 R_EntityMatrix(&identitymatrix);
5720 R_Mesh_ResetTextureState();
5721 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5722 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5723 switch(vid.renderpath)
5725 case RENDERPATH_GL11:
5726 case RENDERPATH_GL13:
5727 case RENDERPATH_GL20:
5728 case RENDERPATH_GLES1:
5729 case RENDERPATH_GLES2:
5730 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5732 case RENDERPATH_D3D9:
5733 case RENDERPATH_D3D10:
5734 case RENDERPATH_D3D11:
5735 case RENDERPATH_SOFT:
5738 GL_CullFace(r_refdef.view.cullface_back);
5743 R_RenderView_UpdateViewVectors
5746 void R_RenderView_UpdateViewVectors(void)
5748 // break apart the view matrix into vectors for various purposes
5749 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5750 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5751 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5752 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5753 // make an inverted copy of the view matrix for tracking sprites
5754 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5757 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5758 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5760 static void R_Water_StartFrame(void)
5763 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5764 r_waterstate_waterplane_t *p;
5765 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5767 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5770 switch(vid.renderpath)
5772 case RENDERPATH_GL20:
5773 case RENDERPATH_D3D9:
5774 case RENDERPATH_D3D10:
5775 case RENDERPATH_D3D11:
5776 case RENDERPATH_SOFT:
5777 case RENDERPATH_GLES2:
5779 case RENDERPATH_GL11:
5780 case RENDERPATH_GL13:
5781 case RENDERPATH_GLES1:
5785 // set waterwidth and waterheight to the water resolution that will be
5786 // used (often less than the screen resolution for faster rendering)
5787 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5789 // calculate desired texture sizes
5790 // can't use water if the card does not support the texture size
5791 if (!r_water.integer || r_showsurfaces.integer)
5792 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5793 else if (vid.support.arb_texture_non_power_of_two)
5795 texturewidth = waterwidth;
5796 textureheight = waterheight;
5797 camerawidth = waterwidth;
5798 cameraheight = waterheight;
5802 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5803 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5804 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5805 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5808 // allocate textures as needed
5809 if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5811 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5812 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5814 if (p->texture_refraction)
5815 R_FreeTexture(p->texture_refraction);
5816 p->texture_refraction = NULL;
5817 if (p->fbo_refraction)
5818 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5819 p->fbo_refraction = 0;
5820 if (p->texture_reflection)
5821 R_FreeTexture(p->texture_reflection);
5822 p->texture_reflection = NULL;
5823 if (p->fbo_reflection)
5824 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5825 p->fbo_reflection = 0;
5826 if (p->texture_camera)
5827 R_FreeTexture(p->texture_camera);
5828 p->texture_camera = NULL;
5830 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5833 memset(&r_fb.water, 0, sizeof(r_fb.water));
5834 r_fb.water.texturewidth = texturewidth;
5835 r_fb.water.textureheight = textureheight;
5836 r_fb.water.camerawidth = camerawidth;
5837 r_fb.water.cameraheight = cameraheight;
5840 if (r_fb.water.texturewidth)
5842 int scaledwidth, scaledheight;
5844 r_fb.water.enabled = true;
5846 // water resolution is usually reduced
5847 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5848 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5849 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5851 // set up variables that will be used in shader setup
5852 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5853 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5854 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5855 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5858 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5859 r_fb.water.numwaterplanes = 0;
5862 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5864 int planeindex, bestplaneindex, vertexindex;
5865 vec3_t mins, maxs, normal, center, v, n;
5866 vec_t planescore, bestplanescore;
5868 r_waterstate_waterplane_t *p;
5869 texture_t *t = R_GetCurrentTexture(surface->texture);
5871 rsurface.texture = t;
5872 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5873 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5874 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5876 // average the vertex normals, find the surface bounds (after deformvertexes)
5877 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5878 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5879 VectorCopy(n, normal);
5880 VectorCopy(v, mins);
5881 VectorCopy(v, maxs);
5882 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5884 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5885 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5886 VectorAdd(normal, n, normal);
5887 mins[0] = min(mins[0], v[0]);
5888 mins[1] = min(mins[1], v[1]);
5889 mins[2] = min(mins[2], v[2]);
5890 maxs[0] = max(maxs[0], v[0]);
5891 maxs[1] = max(maxs[1], v[1]);
5892 maxs[2] = max(maxs[2], v[2]);
5894 VectorNormalize(normal);
5895 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5897 VectorCopy(normal, plane.normal);
5898 VectorNormalize(plane.normal);
5899 plane.dist = DotProduct(center, plane.normal);
5900 PlaneClassify(&plane);
5901 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5903 // skip backfaces (except if nocullface is set)
5904 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5906 VectorNegate(plane.normal, plane.normal);
5908 PlaneClassify(&plane);
5912 // find a matching plane if there is one
5913 bestplaneindex = -1;
5914 bestplanescore = 1048576.0f;
5915 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5917 if(p->camera_entity == t->camera_entity)
5919 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5920 if (bestplaneindex < 0 || bestplanescore > planescore)
5922 bestplaneindex = planeindex;
5923 bestplanescore = planescore;
5927 planeindex = bestplaneindex;
5928 p = r_fb.water.waterplanes + planeindex;
5930 // if this surface does not fit any known plane rendered this frame, add one
5931 if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5933 // store the new plane
5934 planeindex = r_fb.water.numwaterplanes++;
5935 p = r_fb.water.waterplanes + planeindex;
5937 // clear materialflags and pvs
5938 p->materialflags = 0;
5939 p->pvsvalid = false;
5940 p->camera_entity = t->camera_entity;
5941 VectorCopy(mins, p->mins);
5942 VectorCopy(maxs, p->maxs);
5946 // merge mins/maxs when we're adding this surface to the plane
5947 p->mins[0] = min(p->mins[0], mins[0]);
5948 p->mins[1] = min(p->mins[1], mins[1]);
5949 p->mins[2] = min(p->mins[2], mins[2]);
5950 p->maxs[0] = max(p->maxs[0], maxs[0]);
5951 p->maxs[1] = max(p->maxs[1], maxs[1]);
5952 p->maxs[2] = max(p->maxs[2], maxs[2]);
5954 // merge this surface's materialflags into the waterplane
5955 p->materialflags |= t->currentmaterialflags;
5956 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5958 // merge this surface's PVS into the waterplane
5959 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5960 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5962 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5968 extern cvar_t r_drawparticles;
5969 extern cvar_t r_drawdecals;
5971 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5974 r_refdef_view_t originalview;
5975 r_refdef_view_t myview;
5976 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;
5977 r_waterstate_waterplane_t *p;
5979 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5982 originalview = r_refdef.view;
5984 // lowquality hack, temporarily shut down some cvars and restore afterwards
5985 qualityreduction = r_water_lowquality.integer;
5986 if (qualityreduction > 0)
5988 if (qualityreduction >= 1)
5990 old_r_shadows = r_shadows.integer;
5991 old_r_worldrtlight = r_shadow_realtime_world.integer;
5992 old_r_dlight = r_shadow_realtime_dlight.integer;
5993 Cvar_SetValueQuick(&r_shadows, 0);
5994 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5995 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5997 if (qualityreduction >= 2)
5999 old_r_dynamic = r_dynamic.integer;
6000 old_r_particles = r_drawparticles.integer;
6001 old_r_decals = r_drawdecals.integer;
6002 Cvar_SetValueQuick(&r_dynamic, 0);
6003 Cvar_SetValueQuick(&r_drawparticles, 0);
6004 Cvar_SetValueQuick(&r_drawdecals, 0);
6008 // make sure enough textures are allocated
6009 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6011 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6013 if (!p->texture_refraction)
6014 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6015 if (!p->texture_refraction)
6019 if (r_fb.water.depthtexture == NULL)
6020 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6021 if (p->fbo_refraction == 0)
6022 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6025 else if (p->materialflags & MATERIALFLAG_CAMERA)
6027 if (!p->texture_camera)
6028 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
6029 if (!p->texture_camera)
6033 if (r_fb.water.depthtexture == NULL)
6034 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6035 if (p->fbo_camera == 0)
6036 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6040 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6042 if (!p->texture_reflection)
6043 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6044 if (!p->texture_reflection)
6048 if (r_fb.water.depthtexture == NULL)
6049 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6050 if (p->fbo_reflection == 0)
6051 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6057 r_refdef.view = originalview;
6058 r_refdef.view.showdebug = false;
6059 r_refdef.view.width = r_fb.water.waterwidth;
6060 r_refdef.view.height = r_fb.water.waterheight;
6061 r_refdef.view.useclipplane = true;
6062 myview = r_refdef.view;
6063 r_fb.water.renderingscene = true;
6064 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6066 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6068 r_refdef.view = myview;
6069 if(r_water_scissormode.integer)
6071 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6072 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6073 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6076 // render reflected scene and copy into texture
6077 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6078 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6079 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6080 r_refdef.view.clipplane = p->plane;
6081 // reverse the cullface settings for this render
6082 r_refdef.view.cullface_front = GL_FRONT;
6083 r_refdef.view.cullface_back = GL_BACK;
6084 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6086 r_refdef.view.usecustompvs = true;
6088 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6090 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6093 r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6094 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6095 R_ClearScreen(r_refdef.fogenabled);
6096 if(r_water_scissormode.integer & 2)
6097 R_View_UpdateWithScissor(myscissor);
6100 R_AnimCache_CacheVisibleEntities();
6101 if(r_water_scissormode.integer & 1)
6102 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6103 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6105 if (!p->fbo_reflection)
6106 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);
6107 r_fb.water.hideplayer = false;
6110 // render the normal view scene and copy into texture
6111 // (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)
6112 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6114 r_refdef.view = myview;
6115 if(r_water_scissormode.integer)
6117 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6118 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6119 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6122 r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6124 r_refdef.view.clipplane = p->plane;
6125 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6126 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6128 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6130 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6131 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6132 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6133 R_RenderView_UpdateViewVectors();
6134 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6136 r_refdef.view.usecustompvs = true;
6137 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);
6141 PlaneClassify(&r_refdef.view.clipplane);
6143 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6144 R_ClearScreen(r_refdef.fogenabled);
6145 if(r_water_scissormode.integer & 2)
6146 R_View_UpdateWithScissor(myscissor);
6149 R_AnimCache_CacheVisibleEntities();
6150 if(r_water_scissormode.integer & 1)
6151 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6152 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6154 if (!p->fbo_refraction)
6155 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);
6156 r_fb.water.hideplayer = false;
6158 else if (p->materialflags & MATERIALFLAG_CAMERA)
6160 r_refdef.view = myview;
6162 r_refdef.view.clipplane = p->plane;
6163 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6164 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6166 r_refdef.view.width = r_fb.water.camerawidth;
6167 r_refdef.view.height = r_fb.water.cameraheight;
6168 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6169 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6170 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6171 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6173 if(p->camera_entity)
6175 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6176 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6179 // note: all of the view is used for displaying... so
6180 // there is no use in scissoring
6182 // reverse the cullface settings for this render
6183 r_refdef.view.cullface_front = GL_FRONT;
6184 r_refdef.view.cullface_back = GL_BACK;
6185 // also reverse the view matrix
6186 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
6187 R_RenderView_UpdateViewVectors();
6188 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6190 r_refdef.view.usecustompvs = true;
6191 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);
6194 // camera needs no clipplane
6195 r_refdef.view.useclipplane = false;
6197 PlaneClassify(&r_refdef.view.clipplane);
6199 r_fb.water.hideplayer = false;
6201 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6202 R_ClearScreen(r_refdef.fogenabled);
6204 R_AnimCache_CacheVisibleEntities();
6205 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6208 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);
6209 r_fb.water.hideplayer = false;
6213 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6214 r_fb.water.renderingscene = false;
6215 r_refdef.view = originalview;
6216 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6217 if (!r_fb.water.depthtexture)
6218 R_ClearScreen(r_refdef.fogenabled);
6220 R_AnimCache_CacheVisibleEntities();
6223 r_refdef.view = originalview;
6224 r_fb.water.renderingscene = false;
6225 Cvar_SetValueQuick(&r_water, 0);
6226 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6228 // lowquality hack, restore cvars
6229 if (qualityreduction > 0)
6231 if (qualityreduction >= 1)
6233 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6234 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6235 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6237 if (qualityreduction >= 2)
6239 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6240 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6241 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6246 static void R_Bloom_StartFrame(void)
6249 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6250 int viewwidth, viewheight;
6251 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6252 textype_t textype = TEXTYPE_COLORBUFFER;
6254 switch (vid.renderpath)
6256 case RENDERPATH_GL20:
6257 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6258 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6260 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6261 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6264 case RENDERPATH_GL11:
6265 case RENDERPATH_GL13:
6266 case RENDERPATH_GLES1:
6267 case RENDERPATH_GLES2:
6268 case RENDERPATH_D3D9:
6269 case RENDERPATH_D3D10:
6270 case RENDERPATH_D3D11:
6271 r_fb.usedepthtextures = false;
6273 case RENDERPATH_SOFT:
6274 r_fb.usedepthtextures = true;
6278 if (r_viewscale_fpsscaling.integer)
6280 double actualframetime;
6281 double targetframetime;
6283 actualframetime = r_refdef.lastdrawscreentime;
6284 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6285 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6286 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6287 if (r_viewscale_fpsscaling_stepsize.value > 0)
6288 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6289 viewscalefpsadjusted += adjust;
6290 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6293 viewscalefpsadjusted = 1.0f;
6295 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6297 switch(vid.renderpath)
6299 case RENDERPATH_GL20:
6300 case RENDERPATH_D3D9:
6301 case RENDERPATH_D3D10:
6302 case RENDERPATH_D3D11:
6303 case RENDERPATH_SOFT:
6304 case RENDERPATH_GLES2:
6306 case RENDERPATH_GL11:
6307 case RENDERPATH_GL13:
6308 case RENDERPATH_GLES1:
6312 // set bloomwidth and bloomheight to the bloom resolution that will be
6313 // used (often less than the screen resolution for faster rendering)
6314 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6315 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6316 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6317 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6318 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6320 // calculate desired texture sizes
6321 if (vid.support.arb_texture_non_power_of_two)
6323 screentexturewidth = vid.width;
6324 screentextureheight = vid.height;
6325 bloomtexturewidth = r_fb.bloomwidth;
6326 bloomtextureheight = r_fb.bloomheight;
6330 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6331 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6332 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6333 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6336 if ((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))
6338 Cvar_SetValueQuick(&r_bloom, 0);
6339 Cvar_SetValueQuick(&r_motionblur, 0);
6340 Cvar_SetValueQuick(&r_damageblur, 0);
6343 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6345 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6347 && r_viewscale.value == 1.0f
6348 && !r_viewscale_fpsscaling.integer)
6349 screentexturewidth = screentextureheight = 0;
6350 if (!r_bloom.integer)
6351 bloomtexturewidth = bloomtextureheight = 0;
6353 // allocate textures as needed
6354 if (r_fb.screentexturewidth != screentexturewidth
6355 || r_fb.screentextureheight != screentextureheight
6356 || r_fb.bloomtexturewidth != bloomtexturewidth
6357 || r_fb.bloomtextureheight != bloomtextureheight
6358 || r_fb.textype != textype
6359 || useviewfbo != (r_fb.fbo != 0))
6361 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6363 if (r_fb.bloomtexture[i])
6364 R_FreeTexture(r_fb.bloomtexture[i]);
6365 r_fb.bloomtexture[i] = NULL;
6367 if (r_fb.bloomfbo[i])
6368 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6369 r_fb.bloomfbo[i] = 0;
6373 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6376 if (r_fb.colortexture)
6377 R_FreeTexture(r_fb.colortexture);
6378 r_fb.colortexture = NULL;
6380 if (r_fb.depthtexture)
6381 R_FreeTexture(r_fb.depthtexture);
6382 r_fb.depthtexture = NULL;
6384 if (r_fb.ghosttexture)
6385 R_FreeTexture(r_fb.ghosttexture);
6386 r_fb.ghosttexture = NULL;
6388 r_fb.screentexturewidth = screentexturewidth;
6389 r_fb.screentextureheight = screentextureheight;
6390 r_fb.bloomtexturewidth = bloomtexturewidth;
6391 r_fb.bloomtextureheight = bloomtextureheight;
6392 r_fb.textype = textype;
6394 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6396 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6397 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6398 r_fb.ghosttexture_valid = false;
6399 r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6402 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6403 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6404 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6408 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6410 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6412 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6414 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6419 // bloom texture is a different resolution
6420 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6421 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6422 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6423 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6424 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6426 // set up a texcoord array for the full resolution screen image
6427 // (we have to keep this around to copy back during final render)
6428 r_fb.screentexcoord2f[0] = 0;
6429 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6430 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6431 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6432 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6433 r_fb.screentexcoord2f[5] = 0;
6434 r_fb.screentexcoord2f[6] = 0;
6435 r_fb.screentexcoord2f[7] = 0;
6439 for (i = 1;i < 8;i += 2)
6441 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6445 // set up a texcoord array for the reduced resolution bloom image
6446 // (which will be additive blended over the screen image)
6447 r_fb.bloomtexcoord2f[0] = 0;
6448 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6449 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6450 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6451 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6452 r_fb.bloomtexcoord2f[5] = 0;
6453 r_fb.bloomtexcoord2f[6] = 0;
6454 r_fb.bloomtexcoord2f[7] = 0;
6456 switch(vid.renderpath)
6458 case RENDERPATH_GL11:
6459 case RENDERPATH_GL13:
6460 case RENDERPATH_GL20:
6461 case RENDERPATH_SOFT:
6462 case RENDERPATH_GLES1:
6463 case RENDERPATH_GLES2:
6465 case RENDERPATH_D3D9:
6466 case RENDERPATH_D3D10:
6467 case RENDERPATH_D3D11:
6468 for (i = 0;i < 4;i++)
6470 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6471 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6472 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6473 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6478 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6481 r_refdef.view.clear = true;
6484 static void R_Bloom_MakeTexture(void)
6487 float xoffset, yoffset, r, brighten;
6489 float colorscale = r_bloom_colorscale.value;
6491 r_refdef.stats[r_stat_bloom]++;
6494 // this copy is unnecessary since it happens in R_BlendView already
6497 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6498 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6502 // scale down screen texture to the bloom texture size
6504 r_fb.bloomindex = 0;
6505 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6506 R_SetViewport(&r_fb.bloomviewport);
6507 GL_DepthTest(false);
6508 GL_BlendFunc(GL_ONE, GL_ZERO);
6509 GL_Color(colorscale, colorscale, colorscale, 1);
6510 // 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...
6511 switch(vid.renderpath)
6513 case RENDERPATH_GL11:
6514 case RENDERPATH_GL13:
6515 case RENDERPATH_GL20:
6516 case RENDERPATH_GLES1:
6517 case RENDERPATH_GLES2:
6518 case RENDERPATH_SOFT:
6519 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6521 case RENDERPATH_D3D9:
6522 case RENDERPATH_D3D10:
6523 case RENDERPATH_D3D11:
6524 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6527 // TODO: do boxfilter scale-down in shader?
6528 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6529 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6530 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6532 // we now have a properly scaled bloom image
6533 if (!r_fb.bloomfbo[r_fb.bloomindex])
6535 // copy it into the bloom texture
6536 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6537 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6540 // multiply bloom image by itself as many times as desired
6541 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6543 intex = r_fb.bloomtexture[r_fb.bloomindex];
6544 r_fb.bloomindex ^= 1;
6545 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6547 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6548 if (!r_fb.bloomfbo[r_fb.bloomindex])
6550 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6551 GL_Color(r,r,r,1); // apply fix factor
6556 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6557 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6558 GL_Color(1,1,1,1); // no fix factor supported here
6560 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6561 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6562 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6563 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6565 if (!r_fb.bloomfbo[r_fb.bloomindex])
6567 // copy the darkened image to a texture
6568 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6569 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6573 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6574 brighten = r_bloom_brighten.value;
6575 brighten = sqrt(brighten);
6577 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6579 for (dir = 0;dir < 2;dir++)
6581 intex = r_fb.bloomtexture[r_fb.bloomindex];
6582 r_fb.bloomindex ^= 1;
6583 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6584 // blend on at multiple vertical offsets to achieve a vertical blur
6585 // TODO: do offset blends using GLSL
6586 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6587 GL_BlendFunc(GL_ONE, GL_ZERO);
6588 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6589 for (x = -range;x <= range;x++)
6591 if (!dir){xoffset = 0;yoffset = x;}
6592 else {xoffset = x;yoffset = 0;}
6593 xoffset /= (float)r_fb.bloomtexturewidth;
6594 yoffset /= (float)r_fb.bloomtextureheight;
6595 // compute a texcoord array with the specified x and y offset
6596 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6597 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6598 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6599 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6600 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6601 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6602 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6603 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6604 // this r value looks like a 'dot' particle, fading sharply to
6605 // black at the edges
6606 // (probably not realistic but looks good enough)
6607 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6608 //r = brighten/(range*2+1);
6609 r = brighten / (range * 2 + 1);
6611 r *= (1 - x*x/(float)(range*range));
6612 GL_Color(r, r, r, 1);
6613 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6614 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6615 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6616 GL_BlendFunc(GL_ONE, GL_ONE);
6619 if (!r_fb.bloomfbo[r_fb.bloomindex])
6621 // copy the vertically or horizontally blurred bloom view to a texture
6622 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6623 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6628 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6630 unsigned int permutation;
6631 float uservecs[4][4];
6633 R_EntityMatrix(&identitymatrix);
6635 switch (vid.renderpath)
6637 case RENDERPATH_GL20:
6638 case RENDERPATH_D3D9:
6639 case RENDERPATH_D3D10:
6640 case RENDERPATH_D3D11:
6641 case RENDERPATH_SOFT:
6642 case RENDERPATH_GLES2:
6644 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6645 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6646 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6647 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6648 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6650 if (r_fb.colortexture)
6654 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6655 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6658 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6660 // declare variables
6661 float blur_factor, blur_mouseaccel, blur_velocity;
6662 static float blur_average;
6663 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6665 // set a goal for the factoring
6666 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6667 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6668 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6669 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6670 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6671 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6673 // from the goal, pick an averaged value between goal and last value
6674 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6675 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6677 // enforce minimum amount of blur
6678 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6680 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6682 // calculate values into a standard alpha
6683 cl.motionbluralpha = 1 - exp(-
6685 (r_motionblur.value * blur_factor / 80)
6687 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6690 max(0.0001, cl.time - cl.oldtime) // fps independent
6693 // randomization for the blur value to combat persistent ghosting
6694 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6695 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6698 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6699 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6701 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6702 GL_Color(1, 1, 1, cl.motionbluralpha);
6703 switch(vid.renderpath)
6705 case RENDERPATH_GL11:
6706 case RENDERPATH_GL13:
6707 case RENDERPATH_GL20:
6708 case RENDERPATH_GLES1:
6709 case RENDERPATH_GLES2:
6710 case RENDERPATH_SOFT:
6711 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6713 case RENDERPATH_D3D9:
6714 case RENDERPATH_D3D10:
6715 case RENDERPATH_D3D11:
6716 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6719 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6720 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6721 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6724 // updates old view angles for next pass
6725 VectorCopy(cl.viewangles, blur_oldangles);
6727 // copy view into the ghost texture
6728 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6729 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6730 r_fb.ghosttexture_valid = true;
6735 // no r_fb.colortexture means we're rendering to the real fb
6736 // we may still have to do view tint...
6737 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6739 // apply a color tint to the whole view
6740 R_ResetViewRendering2D(0, NULL, NULL);
6741 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6742 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6743 R_SetupShader_Generic_NoTexture(false, true);
6744 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6745 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6747 break; // no screen processing, no bloom, skip it
6750 if (r_fb.bloomtexture[0])
6752 // make the bloom texture
6753 R_Bloom_MakeTexture();
6756 #if _MSC_VER >= 1400
6757 #define sscanf sscanf_s
6759 memset(uservecs, 0, sizeof(uservecs));
6760 if (r_glsl_postprocess_uservec1_enable.integer)
6761 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6762 if (r_glsl_postprocess_uservec2_enable.integer)
6763 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6764 if (r_glsl_postprocess_uservec3_enable.integer)
6765 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6766 if (r_glsl_postprocess_uservec4_enable.integer)
6767 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6769 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6770 GL_Color(1, 1, 1, 1);
6771 GL_BlendFunc(GL_ONE, GL_ZERO);
6773 switch(vid.renderpath)
6775 case RENDERPATH_GL20:
6776 case RENDERPATH_GLES2:
6777 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6778 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6779 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6780 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6781 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6782 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]);
6783 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6784 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]);
6785 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]);
6786 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]);
6787 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]);
6788 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6789 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6790 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);
6792 case RENDERPATH_D3D9:
6794 // 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...
6795 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6796 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6797 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6798 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6799 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6800 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6801 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6802 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6803 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6804 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6805 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6806 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6807 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6808 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6811 case RENDERPATH_D3D10:
6812 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6814 case RENDERPATH_D3D11:
6815 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6817 case RENDERPATH_SOFT:
6818 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6819 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6820 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6821 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6822 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6823 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6824 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6825 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6826 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6827 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6828 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6829 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6830 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6831 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6836 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6837 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6839 case RENDERPATH_GL11:
6840 case RENDERPATH_GL13:
6841 case RENDERPATH_GLES1:
6842 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6844 // apply a color tint to the whole view
6845 R_ResetViewRendering2D(0, NULL, NULL);
6846 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6847 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6848 R_SetupShader_Generic_NoTexture(false, true);
6849 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6850 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6856 matrix4x4_t r_waterscrollmatrix;
6858 void R_UpdateFog(void)
6861 if (gamemode == GAME_NEHAHRA)
6863 if (gl_fogenable.integer)
6865 r_refdef.oldgl_fogenable = true;
6866 r_refdef.fog_density = gl_fogdensity.value;
6867 r_refdef.fog_red = gl_fogred.value;
6868 r_refdef.fog_green = gl_foggreen.value;
6869 r_refdef.fog_blue = gl_fogblue.value;
6870 r_refdef.fog_alpha = 1;
6871 r_refdef.fog_start = 0;
6872 r_refdef.fog_end = gl_skyclip.value;
6873 r_refdef.fog_height = 1<<30;
6874 r_refdef.fog_fadedepth = 128;
6876 else if (r_refdef.oldgl_fogenable)
6878 r_refdef.oldgl_fogenable = false;
6879 r_refdef.fog_density = 0;
6880 r_refdef.fog_red = 0;
6881 r_refdef.fog_green = 0;
6882 r_refdef.fog_blue = 0;
6883 r_refdef.fog_alpha = 0;
6884 r_refdef.fog_start = 0;
6885 r_refdef.fog_end = 0;
6886 r_refdef.fog_height = 1<<30;
6887 r_refdef.fog_fadedepth = 128;
6892 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6893 r_refdef.fog_start = max(0, r_refdef.fog_start);
6894 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6896 if (r_refdef.fog_density && r_drawfog.integer)
6898 r_refdef.fogenabled = true;
6899 // this is the point where the fog reaches 0.9986 alpha, which we
6900 // consider a good enough cutoff point for the texture
6901 // (0.9986 * 256 == 255.6)
6902 if (r_fog_exp2.integer)
6903 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6905 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6906 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6907 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6908 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6909 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6910 R_BuildFogHeightTexture();
6911 // fog color was already set
6912 // update the fog texture
6913 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)
6914 R_BuildFogTexture();
6915 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6916 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6919 r_refdef.fogenabled = false;
6922 if (r_refdef.fog_density)
6924 r_refdef.fogcolor[0] = r_refdef.fog_red;
6925 r_refdef.fogcolor[1] = r_refdef.fog_green;
6926 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6928 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6929 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6930 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6931 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6935 VectorCopy(r_refdef.fogcolor, fogvec);
6936 // color.rgb *= ContrastBoost * SceneBrightness;
6937 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6938 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6939 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6940 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6945 void R_UpdateVariables(void)
6949 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6951 r_refdef.farclip = r_farclip_base.value;
6952 if (r_refdef.scene.worldmodel)
6953 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6954 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6956 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6957 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6958 r_refdef.polygonfactor = 0;
6959 r_refdef.polygonoffset = 0;
6960 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6961 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6963 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6964 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6965 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6966 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6967 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6968 if (FAKELIGHT_ENABLED)
6970 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6972 else if (r_refdef.scene.worldmodel)
6974 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6976 if (r_showsurfaces.integer)
6978 r_refdef.scene.rtworld = false;
6979 r_refdef.scene.rtworldshadows = false;
6980 r_refdef.scene.rtdlight = false;
6981 r_refdef.scene.rtdlightshadows = false;
6982 r_refdef.lightmapintensity = 0;
6985 r_gpuskeletal = false;
6986 switch(vid.renderpath)
6988 case RENDERPATH_GL20:
6989 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6990 case RENDERPATH_D3D9:
6991 case RENDERPATH_D3D10:
6992 case RENDERPATH_D3D11:
6993 case RENDERPATH_SOFT:
6994 case RENDERPATH_GLES2:
6995 if(v_glslgamma.integer && !vid_gammatables_trivial)
6997 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6999 // build GLSL gamma texture
7000 #define RAMPWIDTH 256
7001 unsigned short ramp[RAMPWIDTH * 3];
7002 unsigned char rampbgr[RAMPWIDTH][4];
7005 r_texture_gammaramps_serial = vid_gammatables_serial;
7007 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7008 for(i = 0; i < RAMPWIDTH; ++i)
7010 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7011 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7012 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7015 if (r_texture_gammaramps)
7017 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7021 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7027 // remove GLSL gamma texture
7030 case RENDERPATH_GL11:
7031 case RENDERPATH_GL13:
7032 case RENDERPATH_GLES1:
7037 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7038 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7044 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7045 if( scenetype != r_currentscenetype ) {
7046 // store the old scenetype
7047 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7048 r_currentscenetype = scenetype;
7049 // move in the new scene
7050 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7059 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7061 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7062 if( scenetype == r_currentscenetype ) {
7063 return &r_refdef.scene;
7065 return &r_scenes_store[ scenetype ];
7069 static int R_SortEntities_Compare(const void *ap, const void *bp)
7071 const entity_render_t *a = *(const entity_render_t **)ap;
7072 const entity_render_t *b = *(const entity_render_t **)bp;
7075 if(a->model < b->model)
7077 if(a->model > b->model)
7081 // TODO possibly calculate the REAL skinnum here first using
7083 if(a->skinnum < b->skinnum)
7085 if(a->skinnum > b->skinnum)
7088 // everything we compared is equal
7091 static void R_SortEntities(void)
7093 // below or equal 2 ents, sorting never gains anything
7094 if(r_refdef.scene.numentities <= 2)
7097 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7105 int dpsoftrast_test;
7106 extern cvar_t r_shadow_bouncegrid;
7107 void R_RenderView(void)
7109 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7111 rtexture_t *depthtexture;
7112 rtexture_t *colortexture;
7114 dpsoftrast_test = r_test.integer;
7116 if (r_timereport_active)
7117 R_TimeReport("start");
7118 r_textureframe++; // used only by R_GetCurrentTexture
7119 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7121 if(R_CompileShader_CheckStaticParms())
7124 if (!r_drawentities.integer)
7125 r_refdef.scene.numentities = 0;
7126 else if (r_sortentities.integer)
7129 R_AnimCache_ClearCache();
7131 /* adjust for stereo display */
7132 if(R_Stereo_Active())
7134 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);
7135 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7138 if (r_refdef.view.isoverlay)
7140 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7141 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7142 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7143 R_TimeReport("depthclear");
7145 r_refdef.view.showdebug = false;
7147 r_fb.water.enabled = false;
7148 r_fb.water.numwaterplanes = 0;
7150 R_RenderScene(0, NULL, NULL);
7152 r_refdef.view.matrix = originalmatrix;
7158 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7160 r_refdef.view.matrix = originalmatrix;
7164 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7166 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7167 // in sRGB fallback, behave similar to true sRGB: convert this
7168 // value from linear to sRGB
7169 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7171 R_RenderView_UpdateViewVectors();
7173 R_Shadow_UpdateWorldLightSelection();
7175 R_Bloom_StartFrame();
7177 // apply bloom brightness offset
7178 if(r_fb.bloomtexture[0])
7179 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7181 R_Water_StartFrame();
7183 // now we probably have an fbo to render into
7185 depthtexture = r_fb.depthtexture;
7186 colortexture = r_fb.colortexture;
7189 if (r_timereport_active)
7190 R_TimeReport("viewsetup");
7192 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7194 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7196 R_ClearScreen(r_refdef.fogenabled);
7197 if (r_timereport_active)
7198 R_TimeReport("viewclear");
7200 r_refdef.view.clear = true;
7202 r_refdef.view.showdebug = true;
7205 if (r_timereport_active)
7206 R_TimeReport("visibility");
7208 R_AnimCache_CacheVisibleEntities();
7209 if (r_timereport_active)
7210 R_TimeReport("animcache");
7212 R_Shadow_UpdateBounceGridTexture();
7213 if (r_timereport_active && r_shadow_bouncegrid.integer)
7214 R_TimeReport("bouncegrid");
7216 r_fb.water.numwaterplanes = 0;
7217 if (r_fb.water.enabled)
7218 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7220 R_RenderScene(fbo, depthtexture, colortexture);
7221 r_fb.water.numwaterplanes = 0;
7223 R_BlendView(fbo, depthtexture, colortexture);
7224 if (r_timereport_active)
7225 R_TimeReport("blendview");
7227 GL_Scissor(0, 0, vid.width, vid.height);
7228 GL_ScissorTest(false);
7230 r_refdef.view.matrix = originalmatrix;
7235 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7237 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7239 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7240 if (r_timereport_active)
7241 R_TimeReport("waterworld");
7244 // don't let sound skip if going slow
7245 if (r_refdef.scene.extraupdate)
7248 R_DrawModelsAddWaterPlanes();
7249 if (r_timereport_active)
7250 R_TimeReport("watermodels");
7252 if (r_fb.water.numwaterplanes)
7254 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7255 if (r_timereport_active)
7256 R_TimeReport("waterscenes");
7260 extern cvar_t cl_locs_show;
7261 static void R_DrawLocs(void);
7262 static void R_DrawEntityBBoxes(void);
7263 static void R_DrawModelDecals(void);
7264 extern cvar_t cl_decals_newsystem;
7265 extern qboolean r_shadow_usingdeferredprepass;
7266 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7268 qboolean shadowmapping = false;
7270 if (r_timereport_active)
7271 R_TimeReport("beginscene");
7273 r_refdef.stats[r_stat_renders]++;
7277 // don't let sound skip if going slow
7278 if (r_refdef.scene.extraupdate)
7281 R_MeshQueue_BeginScene();
7285 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);
7287 if (r_timereport_active)
7288 R_TimeReport("skystartframe");
7290 if (cl.csqc_vidvars.drawworld)
7292 // don't let sound skip if going slow
7293 if (r_refdef.scene.extraupdate)
7296 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7298 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7299 if (r_timereport_active)
7300 R_TimeReport("worldsky");
7303 if (R_DrawBrushModelsSky() && r_timereport_active)
7304 R_TimeReport("bmodelsky");
7306 if (skyrendermasked && skyrenderlater)
7308 // we have to force off the water clipping plane while rendering sky
7309 R_SetupView(false, fbo, depthtexture, colortexture);
7311 R_SetupView(true, fbo, depthtexture, colortexture);
7312 if (r_timereport_active)
7313 R_TimeReport("sky");
7317 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7318 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7319 R_Shadow_PrepareModelShadows();
7320 if (r_timereport_active)
7321 R_TimeReport("preparelights");
7323 if (R_Shadow_ShadowMappingEnabled())
7324 shadowmapping = true;
7326 if (r_shadow_usingdeferredprepass)
7327 R_Shadow_DrawPrepass();
7329 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7331 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7332 if (r_timereport_active)
7333 R_TimeReport("worlddepth");
7335 if (r_depthfirst.integer >= 2)
7337 R_DrawModelsDepth();
7338 if (r_timereport_active)
7339 R_TimeReport("modeldepth");
7342 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7344 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7345 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7346 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7347 // don't let sound skip if going slow
7348 if (r_refdef.scene.extraupdate)
7352 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7354 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7355 if (r_timereport_active)
7356 R_TimeReport("world");
7359 // don't let sound skip if going slow
7360 if (r_refdef.scene.extraupdate)
7364 if (r_timereport_active)
7365 R_TimeReport("models");
7367 // don't let sound skip if going slow
7368 if (r_refdef.scene.extraupdate)
7371 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7373 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7374 R_DrawModelShadows(fbo, depthtexture, colortexture);
7375 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7376 // don't let sound skip if going slow
7377 if (r_refdef.scene.extraupdate)
7381 if (!r_shadow_usingdeferredprepass)
7383 R_Shadow_DrawLights();
7384 if (r_timereport_active)
7385 R_TimeReport("rtlights");
7388 // don't let sound skip if going slow
7389 if (r_refdef.scene.extraupdate)
7392 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7394 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7395 R_DrawModelShadows(fbo, depthtexture, colortexture);
7396 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7397 // don't let sound skip if going slow
7398 if (r_refdef.scene.extraupdate)
7402 if (cl.csqc_vidvars.drawworld)
7404 if (cl_decals_newsystem.integer)
7406 R_DrawModelDecals();
7407 if (r_timereport_active)
7408 R_TimeReport("modeldecals");
7413 if (r_timereport_active)
7414 R_TimeReport("decals");
7418 if (r_timereport_active)
7419 R_TimeReport("particles");
7422 if (r_timereport_active)
7423 R_TimeReport("explosions");
7425 R_DrawLightningBeams();
7426 if (r_timereport_active)
7427 R_TimeReport("lightning");
7431 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7433 if (r_refdef.view.showdebug)
7435 if (cl_locs_show.integer)
7438 if (r_timereport_active)
7439 R_TimeReport("showlocs");
7442 if (r_drawportals.integer)
7445 if (r_timereport_active)
7446 R_TimeReport("portals");
7449 if (r_showbboxes.value > 0)
7451 R_DrawEntityBBoxes();
7452 if (r_timereport_active)
7453 R_TimeReport("bboxes");
7457 if (r_transparent.integer)
7459 R_MeshQueue_RenderTransparent();
7460 if (r_timereport_active)
7461 R_TimeReport("drawtrans");
7464 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))
7466 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7467 if (r_timereport_active)
7468 R_TimeReport("worlddebug");
7469 R_DrawModelsDebug();
7470 if (r_timereport_active)
7471 R_TimeReport("modeldebug");
7474 if (cl.csqc_vidvars.drawworld)
7476 R_Shadow_DrawCoronas();
7477 if (r_timereport_active)
7478 R_TimeReport("coronas");
7483 GL_DepthTest(false);
7484 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7485 GL_Color(1, 1, 1, 1);
7486 qglBegin(GL_POLYGON);
7487 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7488 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7489 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7490 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7492 qglBegin(GL_POLYGON);
7493 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]);
7494 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]);
7495 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]);
7496 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]);
7498 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7502 // don't let sound skip if going slow
7503 if (r_refdef.scene.extraupdate)
7507 static const unsigned short bboxelements[36] =
7517 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7520 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7522 RSurf_ActiveWorldEntity();
7524 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7525 GL_DepthMask(false);
7526 GL_DepthRange(0, 1);
7527 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7528 // R_Mesh_ResetTextureState();
7530 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7531 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7532 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7533 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7534 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7535 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7536 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7537 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7538 R_FillColors(color4f, 8, cr, cg, cb, ca);
7539 if (r_refdef.fogenabled)
7541 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7543 f1 = RSurf_FogVertex(v);
7545 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7546 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7547 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7550 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7551 R_Mesh_ResetTextureState();
7552 R_SetupShader_Generic_NoTexture(false, false);
7553 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7556 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7558 prvm_prog_t *prog = SVVM_prog;
7561 prvm_edict_t *edict;
7563 // this function draws bounding boxes of server entities
7567 GL_CullFace(GL_NONE);
7568 R_SetupShader_Generic_NoTexture(false, false);
7570 for (i = 0;i < numsurfaces;i++)
7572 edict = PRVM_EDICT_NUM(surfacelist[i]);
7573 switch ((int)PRVM_serveredictfloat(edict, solid))
7575 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7576 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7577 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7578 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7579 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7580 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7581 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7583 color[3] *= r_showbboxes.value;
7584 color[3] = bound(0, color[3], 1);
7585 GL_DepthTest(!r_showdisabledepthtest.integer);
7586 GL_CullFace(r_refdef.view.cullface_front);
7587 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7591 static void R_DrawEntityBBoxes(void)
7594 prvm_edict_t *edict;
7596 prvm_prog_t *prog = SVVM_prog;
7598 // this function draws bounding boxes of server entities
7602 for (i = 0;i < prog->num_edicts;i++)
7604 edict = PRVM_EDICT_NUM(i);
7605 if (edict->priv.server->free)
7607 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7608 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7610 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7612 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7613 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7617 static const int nomodelelement3i[24] =
7629 static const unsigned short nomodelelement3s[24] =
7641 static const float nomodelvertex3f[6*3] =
7651 static const float nomodelcolor4f[6*4] =
7653 0.0f, 0.0f, 0.5f, 1.0f,
7654 0.0f, 0.0f, 0.5f, 1.0f,
7655 0.0f, 0.5f, 0.0f, 1.0f,
7656 0.0f, 0.5f, 0.0f, 1.0f,
7657 0.5f, 0.0f, 0.0f, 1.0f,
7658 0.5f, 0.0f, 0.0f, 1.0f
7661 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7667 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);
7669 // this is only called once per entity so numsurfaces is always 1, and
7670 // surfacelist is always {0}, so this code does not handle batches
7672 if (rsurface.ent_flags & RENDER_ADDITIVE)
7674 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7675 GL_DepthMask(false);
7677 else if (rsurface.colormod[3] < 1)
7679 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7680 GL_DepthMask(false);
7684 GL_BlendFunc(GL_ONE, GL_ZERO);
7687 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7688 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7689 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7690 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7691 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7692 for (i = 0, c = color4f;i < 6;i++, c += 4)
7694 c[0] *= rsurface.colormod[0];
7695 c[1] *= rsurface.colormod[1];
7696 c[2] *= rsurface.colormod[2];
7697 c[3] *= rsurface.colormod[3];
7699 if (r_refdef.fogenabled)
7701 for (i = 0, c = color4f;i < 6;i++, c += 4)
7703 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7705 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7706 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7707 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7710 // R_Mesh_ResetTextureState();
7711 R_SetupShader_Generic_NoTexture(false, false);
7712 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7713 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7716 void R_DrawNoModel(entity_render_t *ent)
7719 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7720 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7721 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7723 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7726 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7728 vec3_t right1, right2, diff, normal;
7730 VectorSubtract (org2, org1, normal);
7732 // calculate 'right' vector for start
7733 VectorSubtract (r_refdef.view.origin, org1, diff);
7734 CrossProduct (normal, diff, right1);
7735 VectorNormalize (right1);
7737 // calculate 'right' vector for end
7738 VectorSubtract (r_refdef.view.origin, org2, diff);
7739 CrossProduct (normal, diff, right2);
7740 VectorNormalize (right2);
7742 vert[ 0] = org1[0] + width * right1[0];
7743 vert[ 1] = org1[1] + width * right1[1];
7744 vert[ 2] = org1[2] + width * right1[2];
7745 vert[ 3] = org1[0] - width * right1[0];
7746 vert[ 4] = org1[1] - width * right1[1];
7747 vert[ 5] = org1[2] - width * right1[2];
7748 vert[ 6] = org2[0] - width * right2[0];
7749 vert[ 7] = org2[1] - width * right2[1];
7750 vert[ 8] = org2[2] - width * right2[2];
7751 vert[ 9] = org2[0] + width * right2[0];
7752 vert[10] = org2[1] + width * right2[1];
7753 vert[11] = org2[2] + width * right2[2];
7756 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)
7758 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7759 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7760 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7761 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7762 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7763 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7764 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7765 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7766 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7767 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7768 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7769 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7772 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7777 VectorSet(v, x, y, z);
7778 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7779 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7781 if (i == mesh->numvertices)
7783 if (mesh->numvertices < mesh->maxvertices)
7785 VectorCopy(v, vertex3f);
7786 mesh->numvertices++;
7788 return mesh->numvertices;
7794 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7798 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7799 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7800 e = mesh->element3i + mesh->numtriangles * 3;
7801 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7803 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7804 if (mesh->numtriangles < mesh->maxtriangles)
7809 mesh->numtriangles++;
7811 element[1] = element[2];
7815 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7819 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7820 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7821 e = mesh->element3i + mesh->numtriangles * 3;
7822 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7824 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7825 if (mesh->numtriangles < mesh->maxtriangles)
7830 mesh->numtriangles++;
7832 element[1] = element[2];
7836 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7837 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7839 int planenum, planenum2;
7842 mplane_t *plane, *plane2;
7844 double temppoints[2][256*3];
7845 // figure out how large a bounding box we need to properly compute this brush
7847 for (w = 0;w < numplanes;w++)
7848 maxdist = max(maxdist, fabs(planes[w].dist));
7849 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7850 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7851 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7855 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7856 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7858 if (planenum2 == planenum)
7860 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);
7863 if (tempnumpoints < 3)
7865 // generate elements forming a triangle fan for this polygon
7866 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7870 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)
7872 texturelayer_t *layer;
7873 layer = t->currentlayers + t->currentnumlayers++;
7875 layer->depthmask = depthmask;
7876 layer->blendfunc1 = blendfunc1;
7877 layer->blendfunc2 = blendfunc2;
7878 layer->texture = texture;
7879 layer->texmatrix = *matrix;
7880 layer->color[0] = r;
7881 layer->color[1] = g;
7882 layer->color[2] = b;
7883 layer->color[3] = a;
7886 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7888 if(parms[0] == 0 && parms[1] == 0)
7890 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7891 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7896 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7899 index = parms[2] + rsurface.shadertime * parms[3];
7900 index -= floor(index);
7901 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7904 case Q3WAVEFUNC_NONE:
7905 case Q3WAVEFUNC_NOISE:
7906 case Q3WAVEFUNC_COUNT:
7909 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7910 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7911 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7912 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7913 case Q3WAVEFUNC_TRIANGLE:
7915 f = index - floor(index);
7928 f = parms[0] + parms[1] * f;
7929 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7930 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7934 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7940 matrix4x4_t matrix, temp;
7941 switch(tcmod->tcmod)
7945 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7946 matrix = r_waterscrollmatrix;
7948 matrix = identitymatrix;
7950 case Q3TCMOD_ENTITYTRANSLATE:
7951 // this is used in Q3 to allow the gamecode to control texcoord
7952 // scrolling on the entity, which is not supported in darkplaces yet.
7953 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7955 case Q3TCMOD_ROTATE:
7956 f = tcmod->parms[0] * rsurface.shadertime;
7957 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7958 Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7959 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7962 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7964 case Q3TCMOD_SCROLL:
7965 // extra care is needed because of precision breakdown with large values of time
7966 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7967 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7968 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7970 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7971 w = (int) tcmod->parms[0];
7972 h = (int) tcmod->parms[1];
7973 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7975 idx = (int) floor(f * w * h);
7976 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7978 case Q3TCMOD_STRETCH:
7979 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7980 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7982 case Q3TCMOD_TRANSFORM:
7983 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7984 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7985 VectorSet(tcmat + 6, 0 , 0 , 1);
7986 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7987 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7989 case Q3TCMOD_TURBULENT:
7990 // this is handled in the RSurf_PrepareVertices function
7991 matrix = identitymatrix;
7995 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7998 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8000 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8001 char name[MAX_QPATH];
8002 skinframe_t *skinframe;
8003 unsigned char pixels[296*194];
8004 strlcpy(cache->name, skinname, sizeof(cache->name));
8005 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8006 if (developer_loading.integer)
8007 Con_Printf("loading %s\n", name);
8008 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8009 if (!skinframe || !skinframe->base)
8012 fs_offset_t filesize;
8014 f = FS_LoadFile(name, tempmempool, true, &filesize);
8017 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8018 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8022 cache->skinframe = skinframe;
8025 texture_t *R_GetCurrentTexture(texture_t *t)
8028 const entity_render_t *ent = rsurface.entity;
8029 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8030 q3shaderinfo_layer_tcmod_t *tcmod;
8032 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8033 return t->currentframe;
8034 t->update_lastrenderframe = r_textureframe;
8035 t->update_lastrenderentity = (void *)ent;
8037 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8038 t->camera_entity = ent->entitynumber;
8040 t->camera_entity = 0;
8042 // switch to an alternate material if this is a q1bsp animated material
8044 texture_t *texture = t;
8045 int s = rsurface.ent_skinnum;
8046 if ((unsigned int)s >= (unsigned int)model->numskins)
8048 if (model->skinscenes)
8050 if (model->skinscenes[s].framecount > 1)
8051 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8053 s = model->skinscenes[s].firstframe;
8056 t = t + s * model->num_surfaces;
8059 // use an alternate animation if the entity's frame is not 0,
8060 // and only if the texture has an alternate animation
8061 if (rsurface.ent_alttextures && t->anim_total[1])
8062 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8064 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8066 texture->currentframe = t;
8069 // update currentskinframe to be a qw skin or animation frame
8070 if (rsurface.ent_qwskin >= 0)
8072 i = rsurface.ent_qwskin;
8073 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8075 r_qwskincache_size = cl.maxclients;
8077 Mem_Free(r_qwskincache);
8078 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8080 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8081 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8082 t->currentskinframe = r_qwskincache[i].skinframe;
8083 if (t->currentskinframe == NULL)
8084 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8086 else if (t->numskinframes >= 2)
8087 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8088 if (t->backgroundnumskinframes >= 2)
8089 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8091 t->currentmaterialflags = t->basematerialflags;
8092 t->currentalpha = rsurface.colormod[3];
8093 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8094 t->currentalpha *= r_wateralpha.value;
8095 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8096 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8097 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8098 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8099 if (!(rsurface.ent_flags & RENDER_LIGHT))
8100 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8101 else if (FAKELIGHT_ENABLED)
8103 // no modellight if using fakelight for the map
8105 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8107 // pick a model lighting mode
8108 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8109 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8111 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8113 if (rsurface.ent_flags & RENDER_ADDITIVE)
8114 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8115 else if (t->currentalpha < 1)
8116 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8117 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8118 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8119 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8120 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8121 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8122 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8123 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8124 if (t->backgroundnumskinframes)
8125 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8126 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8128 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8129 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8132 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8133 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8135 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8136 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8138 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8139 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8141 // there is no tcmod
8142 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8144 t->currenttexmatrix = r_waterscrollmatrix;
8145 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8147 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8149 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8150 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8153 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8154 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8155 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8156 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8158 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8159 if (t->currentskinframe->qpixels)
8160 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8161 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8162 if (!t->basetexture)
8163 t->basetexture = r_texture_notexture;
8164 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8165 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8166 t->nmaptexture = t->currentskinframe->nmap;
8167 if (!t->nmaptexture)
8168 t->nmaptexture = r_texture_blanknormalmap;
8169 t->glosstexture = r_texture_black;
8170 t->glowtexture = t->currentskinframe->glow;
8171 t->fogtexture = t->currentskinframe->fog;
8172 t->reflectmasktexture = t->currentskinframe->reflect;
8173 if (t->backgroundnumskinframes)
8175 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8176 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8177 t->backgroundglosstexture = r_texture_black;
8178 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8179 if (!t->backgroundnmaptexture)
8180 t->backgroundnmaptexture = r_texture_blanknormalmap;
8181 // make sure that if glow is going to be used, both textures are not NULL
8182 if (!t->backgroundglowtexture && t->glowtexture)
8183 t->backgroundglowtexture = r_texture_black;
8184 if (!t->glowtexture && t->backgroundglowtexture)
8185 t->glowtexture = r_texture_black;
8189 t->backgroundbasetexture = r_texture_white;
8190 t->backgroundnmaptexture = r_texture_blanknormalmap;
8191 t->backgroundglosstexture = r_texture_black;
8192 t->backgroundglowtexture = NULL;
8194 t->specularpower = r_shadow_glossexponent.value;
8195 // TODO: store reference values for these in the texture?
8196 t->specularscale = 0;
8197 if (r_shadow_gloss.integer > 0)
8199 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8201 if (r_shadow_glossintensity.value > 0)
8203 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8204 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8205 t->specularscale = r_shadow_glossintensity.value;
8208 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8210 t->glosstexture = r_texture_white;
8211 t->backgroundglosstexture = r_texture_white;
8212 t->specularscale = r_shadow_gloss2intensity.value;
8213 t->specularpower = r_shadow_gloss2exponent.value;
8216 t->specularscale *= t->specularscalemod;
8217 t->specularpower *= t->specularpowermod;
8218 t->rtlightambient = 0;
8220 // lightmaps mode looks bad with dlights using actual texturing, so turn
8221 // off the colormap and glossmap, but leave the normalmap on as it still
8222 // accurately represents the shading involved
8223 if (gl_lightmaps.integer)
8225 t->basetexture = r_texture_grey128;
8226 t->pantstexture = r_texture_black;
8227 t->shirttexture = r_texture_black;
8228 if (gl_lightmaps.integer < 2)
8229 t->nmaptexture = r_texture_blanknormalmap;
8230 t->glosstexture = r_texture_black;
8231 t->glowtexture = NULL;
8232 t->fogtexture = NULL;
8233 t->reflectmasktexture = NULL;
8234 t->backgroundbasetexture = NULL;
8235 if (gl_lightmaps.integer < 2)
8236 t->backgroundnmaptexture = r_texture_blanknormalmap;
8237 t->backgroundglosstexture = r_texture_black;
8238 t->backgroundglowtexture = NULL;
8239 t->specularscale = 0;
8240 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8243 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8244 VectorClear(t->dlightcolor);
8245 t->currentnumlayers = 0;
8246 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8248 int blendfunc1, blendfunc2;
8250 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8252 blendfunc1 = GL_SRC_ALPHA;
8253 blendfunc2 = GL_ONE;
8255 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8257 blendfunc1 = GL_SRC_ALPHA;
8258 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8260 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8262 blendfunc1 = t->customblendfunc[0];
8263 blendfunc2 = t->customblendfunc[1];
8267 blendfunc1 = GL_ONE;
8268 blendfunc2 = GL_ZERO;
8270 // don't colormod evilblend textures
8271 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8272 VectorSet(t->lightmapcolor, 1, 1, 1);
8273 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8274 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8276 // fullbright is not affected by r_refdef.lightmapintensity
8277 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]);
8278 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8279 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]);
8280 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8281 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]);
8285 vec3_t ambientcolor;
8287 // set the color tint used for lights affecting this surface
8288 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8290 // q3bsp has no lightmap updates, so the lightstylevalue that
8291 // would normally be baked into the lightmap must be
8292 // applied to the color
8293 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8294 if (model->type == mod_brushq3)
8295 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8296 colorscale *= r_refdef.lightmapintensity;
8297 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8298 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8299 // basic lit geometry
8300 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]);
8301 // add pants/shirt if needed
8302 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8303 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]);
8304 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8305 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]);
8306 // now add ambient passes if needed
8307 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8309 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]);
8310 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8311 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]);
8312 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8313 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]);
8316 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8317 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]);
8318 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8320 // if this is opaque use alpha blend which will darken the earlier
8323 // if this is an alpha blended material, all the earlier passes
8324 // were darkened by fog already, so we only need to add the fog
8325 // color ontop through the fog mask texture
8327 // if this is an additive blended material, all the earlier passes
8328 // were darkened by fog already, and we should not add fog color
8329 // (because the background was not darkened, there is no fog color
8330 // that was lost behind it).
8331 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]);
8335 return t->currentframe;
8338 rsurfacestate_t rsurface;
8340 void RSurf_ActiveWorldEntity(void)
8342 dp_model_t *model = r_refdef.scene.worldmodel;
8343 //if (rsurface.entity == r_refdef.scene.worldentity)
8345 rsurface.entity = r_refdef.scene.worldentity;
8346 rsurface.skeleton = NULL;
8347 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8348 rsurface.ent_skinnum = 0;
8349 rsurface.ent_qwskin = -1;
8350 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8351 rsurface.shadertime = r_refdef.scene.time;
8352 rsurface.matrix = identitymatrix;
8353 rsurface.inversematrix = identitymatrix;
8354 rsurface.matrixscale = 1;
8355 rsurface.inversematrixscale = 1;
8356 R_EntityMatrix(&identitymatrix);
8357 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8358 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8359 rsurface.fograngerecip = r_refdef.fograngerecip;
8360 rsurface.fogheightfade = r_refdef.fogheightfade;
8361 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8362 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8363 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8364 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8365 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8366 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8367 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8368 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8369 rsurface.colormod[3] = 1;
8370 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);
8371 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8372 rsurface.frameblend[0].lerp = 1;
8373 rsurface.ent_alttextures = false;
8374 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8375 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8376 rsurface.entityskeletaltransform3x4 = NULL;
8377 rsurface.entityskeletaltransform3x4buffer = NULL;
8378 rsurface.entityskeletaltransform3x4offset = 0;
8379 rsurface.entityskeletaltransform3x4size = 0;;
8380 rsurface.entityskeletalnumtransforms = 0;
8381 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8382 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8383 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8384 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8385 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8386 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8387 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8388 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8389 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8390 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8391 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8392 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8393 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8394 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8395 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8396 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8397 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8398 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8399 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8400 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8401 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8402 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8403 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8404 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8405 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8406 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8407 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8408 rsurface.modelelement3i = model->surfmesh.data_element3i;
8409 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8410 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8411 rsurface.modelelement3s = model->surfmesh.data_element3s;
8412 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8413 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8414 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8415 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8416 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8417 rsurface.modelsurfaces = model->data_surfaces;
8418 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8419 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8420 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8421 rsurface.modelgeneratedvertex = false;
8422 rsurface.batchgeneratedvertex = false;
8423 rsurface.batchfirstvertex = 0;
8424 rsurface.batchnumvertices = 0;
8425 rsurface.batchfirsttriangle = 0;
8426 rsurface.batchnumtriangles = 0;
8427 rsurface.batchvertex3f = NULL;
8428 rsurface.batchvertex3f_vertexbuffer = NULL;
8429 rsurface.batchvertex3f_bufferoffset = 0;
8430 rsurface.batchsvector3f = NULL;
8431 rsurface.batchsvector3f_vertexbuffer = NULL;
8432 rsurface.batchsvector3f_bufferoffset = 0;
8433 rsurface.batchtvector3f = NULL;
8434 rsurface.batchtvector3f_vertexbuffer = NULL;
8435 rsurface.batchtvector3f_bufferoffset = 0;
8436 rsurface.batchnormal3f = NULL;
8437 rsurface.batchnormal3f_vertexbuffer = NULL;
8438 rsurface.batchnormal3f_bufferoffset = 0;
8439 rsurface.batchlightmapcolor4f = NULL;
8440 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8441 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8442 rsurface.batchtexcoordtexture2f = NULL;
8443 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8444 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8445 rsurface.batchtexcoordlightmap2f = NULL;
8446 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8447 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8448 rsurface.batchskeletalindex4ub = NULL;
8449 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8450 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8451 rsurface.batchskeletalweight4ub = NULL;
8452 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8453 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8454 rsurface.batchvertexmesh = NULL;
8455 rsurface.batchvertexmesh_vertexbuffer = NULL;
8456 rsurface.batchvertexmesh_bufferoffset = 0;
8457 rsurface.batchelement3i = NULL;
8458 rsurface.batchelement3i_indexbuffer = NULL;
8459 rsurface.batchelement3i_bufferoffset = 0;
8460 rsurface.batchelement3s = NULL;
8461 rsurface.batchelement3s_indexbuffer = NULL;
8462 rsurface.batchelement3s_bufferoffset = 0;
8463 rsurface.passcolor4f = NULL;
8464 rsurface.passcolor4f_vertexbuffer = NULL;
8465 rsurface.passcolor4f_bufferoffset = 0;
8466 rsurface.forcecurrenttextureupdate = false;
8469 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8471 dp_model_t *model = ent->model;
8472 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8474 rsurface.entity = (entity_render_t *)ent;
8475 rsurface.skeleton = ent->skeleton;
8476 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8477 rsurface.ent_skinnum = ent->skinnum;
8478 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;
8479 rsurface.ent_flags = ent->flags;
8480 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8481 rsurface.matrix = ent->matrix;
8482 rsurface.inversematrix = ent->inversematrix;
8483 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8484 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8485 R_EntityMatrix(&rsurface.matrix);
8486 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8487 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8488 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8489 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8490 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8491 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8492 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8493 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8494 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8495 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8496 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8497 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8498 rsurface.colormod[3] = ent->alpha;
8499 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8500 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8501 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8502 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8503 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8504 if (ent->model->brush.submodel && !prepass)
8506 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8507 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8509 // if the animcache code decided it should use the shader path, skip the deform step
8510 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8511 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8512 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8513 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8514 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8515 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8517 if (ent->animcache_vertex3f)
8519 r_refdef.stats[r_stat_batch_entitycache_count]++;
8520 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8521 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8522 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8523 rsurface.modelvertex3f = ent->animcache_vertex3f;
8524 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8525 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8526 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8527 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8528 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8529 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8530 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8531 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8532 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8533 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8534 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8535 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8536 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8537 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8539 else if (wanttangents)
8541 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8542 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8543 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8544 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8545 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8546 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8547 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8548 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8549 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8550 rsurface.modelvertexmesh = NULL;
8551 rsurface.modelvertexmesh_vertexbuffer = NULL;
8552 rsurface.modelvertexmesh_bufferoffset = 0;
8553 rsurface.modelvertex3f_vertexbuffer = NULL;
8554 rsurface.modelvertex3f_bufferoffset = 0;
8555 rsurface.modelvertex3f_vertexbuffer = 0;
8556 rsurface.modelvertex3f_bufferoffset = 0;
8557 rsurface.modelsvector3f_vertexbuffer = 0;
8558 rsurface.modelsvector3f_bufferoffset = 0;
8559 rsurface.modeltvector3f_vertexbuffer = 0;
8560 rsurface.modeltvector3f_bufferoffset = 0;
8561 rsurface.modelnormal3f_vertexbuffer = 0;
8562 rsurface.modelnormal3f_bufferoffset = 0;
8564 else if (wantnormals)
8566 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8567 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8568 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8569 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8570 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8571 rsurface.modelsvector3f = NULL;
8572 rsurface.modeltvector3f = NULL;
8573 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8574 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8575 rsurface.modelvertexmesh = NULL;
8576 rsurface.modelvertexmesh_vertexbuffer = NULL;
8577 rsurface.modelvertexmesh_bufferoffset = 0;
8578 rsurface.modelvertex3f_vertexbuffer = NULL;
8579 rsurface.modelvertex3f_bufferoffset = 0;
8580 rsurface.modelvertex3f_vertexbuffer = 0;
8581 rsurface.modelvertex3f_bufferoffset = 0;
8582 rsurface.modelsvector3f_vertexbuffer = 0;
8583 rsurface.modelsvector3f_bufferoffset = 0;
8584 rsurface.modeltvector3f_vertexbuffer = 0;
8585 rsurface.modeltvector3f_bufferoffset = 0;
8586 rsurface.modelnormal3f_vertexbuffer = 0;
8587 rsurface.modelnormal3f_bufferoffset = 0;
8591 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8592 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8593 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8594 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8595 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8596 rsurface.modelsvector3f = NULL;
8597 rsurface.modeltvector3f = NULL;
8598 rsurface.modelnormal3f = NULL;
8599 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8600 rsurface.modelvertexmesh = NULL;
8601 rsurface.modelvertexmesh_vertexbuffer = NULL;
8602 rsurface.modelvertexmesh_bufferoffset = 0;
8603 rsurface.modelvertex3f_vertexbuffer = NULL;
8604 rsurface.modelvertex3f_bufferoffset = 0;
8605 rsurface.modelvertex3f_vertexbuffer = 0;
8606 rsurface.modelvertex3f_bufferoffset = 0;
8607 rsurface.modelsvector3f_vertexbuffer = 0;
8608 rsurface.modelsvector3f_bufferoffset = 0;
8609 rsurface.modeltvector3f_vertexbuffer = 0;
8610 rsurface.modeltvector3f_bufferoffset = 0;
8611 rsurface.modelnormal3f_vertexbuffer = 0;
8612 rsurface.modelnormal3f_bufferoffset = 0;
8614 rsurface.modelgeneratedvertex = true;
8618 if (rsurface.entityskeletaltransform3x4)
8620 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8621 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8622 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8623 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8627 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8628 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8629 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8630 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8632 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8633 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8634 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8635 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8636 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8637 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8638 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8639 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8640 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8641 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8642 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8643 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8644 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8645 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8646 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8647 rsurface.modelgeneratedvertex = false;
8649 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8650 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8651 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8652 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8653 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8654 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8655 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8656 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8657 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8658 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8659 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8660 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8661 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8662 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8663 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8664 rsurface.modelelement3i = model->surfmesh.data_element3i;
8665 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8666 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8667 rsurface.modelelement3s = model->surfmesh.data_element3s;
8668 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8669 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8670 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8671 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8672 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8673 rsurface.modelsurfaces = model->data_surfaces;
8674 rsurface.batchgeneratedvertex = false;
8675 rsurface.batchfirstvertex = 0;
8676 rsurface.batchnumvertices = 0;
8677 rsurface.batchfirsttriangle = 0;
8678 rsurface.batchnumtriangles = 0;
8679 rsurface.batchvertex3f = NULL;
8680 rsurface.batchvertex3f_vertexbuffer = NULL;
8681 rsurface.batchvertex3f_bufferoffset = 0;
8682 rsurface.batchsvector3f = NULL;
8683 rsurface.batchsvector3f_vertexbuffer = NULL;
8684 rsurface.batchsvector3f_bufferoffset = 0;
8685 rsurface.batchtvector3f = NULL;
8686 rsurface.batchtvector3f_vertexbuffer = NULL;
8687 rsurface.batchtvector3f_bufferoffset = 0;
8688 rsurface.batchnormal3f = NULL;
8689 rsurface.batchnormal3f_vertexbuffer = NULL;
8690 rsurface.batchnormal3f_bufferoffset = 0;
8691 rsurface.batchlightmapcolor4f = NULL;
8692 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8693 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8694 rsurface.batchtexcoordtexture2f = NULL;
8695 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8696 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8697 rsurface.batchtexcoordlightmap2f = NULL;
8698 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8699 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8700 rsurface.batchskeletalindex4ub = NULL;
8701 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8702 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8703 rsurface.batchskeletalweight4ub = NULL;
8704 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8705 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8706 rsurface.batchvertexmesh = NULL;
8707 rsurface.batchvertexmesh_vertexbuffer = NULL;
8708 rsurface.batchvertexmesh_bufferoffset = 0;
8709 rsurface.batchelement3i = NULL;
8710 rsurface.batchelement3i_indexbuffer = NULL;
8711 rsurface.batchelement3i_bufferoffset = 0;
8712 rsurface.batchelement3s = NULL;
8713 rsurface.batchelement3s_indexbuffer = NULL;
8714 rsurface.batchelement3s_bufferoffset = 0;
8715 rsurface.passcolor4f = NULL;
8716 rsurface.passcolor4f_vertexbuffer = NULL;
8717 rsurface.passcolor4f_bufferoffset = 0;
8718 rsurface.forcecurrenttextureupdate = false;
8721 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)
8723 rsurface.entity = r_refdef.scene.worldentity;
8724 rsurface.skeleton = NULL;
8725 rsurface.ent_skinnum = 0;
8726 rsurface.ent_qwskin = -1;
8727 rsurface.ent_flags = entflags;
8728 rsurface.shadertime = r_refdef.scene.time - shadertime;
8729 rsurface.modelnumvertices = numvertices;
8730 rsurface.modelnumtriangles = numtriangles;
8731 rsurface.matrix = *matrix;
8732 rsurface.inversematrix = *inversematrix;
8733 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8734 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8735 R_EntityMatrix(&rsurface.matrix);
8736 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8737 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8738 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8739 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8740 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8741 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8742 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8743 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8744 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8745 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8746 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8747 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8748 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);
8749 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8750 rsurface.frameblend[0].lerp = 1;
8751 rsurface.ent_alttextures = false;
8752 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8753 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8754 rsurface.entityskeletaltransform3x4 = NULL;
8755 rsurface.entityskeletaltransform3x4buffer = NULL;
8756 rsurface.entityskeletaltransform3x4offset = 0;
8757 rsurface.entityskeletaltransform3x4size = 0;
8758 rsurface.entityskeletalnumtransforms = 0;
8759 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8760 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8761 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8762 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8765 rsurface.modelvertex3f = (float *)vertex3f;
8766 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8767 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8768 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8770 else if (wantnormals)
8772 rsurface.modelvertex3f = (float *)vertex3f;
8773 rsurface.modelsvector3f = NULL;
8774 rsurface.modeltvector3f = NULL;
8775 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8779 rsurface.modelvertex3f = (float *)vertex3f;
8780 rsurface.modelsvector3f = NULL;
8781 rsurface.modeltvector3f = NULL;
8782 rsurface.modelnormal3f = NULL;
8784 rsurface.modelvertexmesh = NULL;
8785 rsurface.modelvertexmesh_vertexbuffer = NULL;
8786 rsurface.modelvertexmesh_bufferoffset = 0;
8787 rsurface.modelvertex3f_vertexbuffer = 0;
8788 rsurface.modelvertex3f_bufferoffset = 0;
8789 rsurface.modelsvector3f_vertexbuffer = 0;
8790 rsurface.modelsvector3f_bufferoffset = 0;
8791 rsurface.modeltvector3f_vertexbuffer = 0;
8792 rsurface.modeltvector3f_bufferoffset = 0;
8793 rsurface.modelnormal3f_vertexbuffer = 0;
8794 rsurface.modelnormal3f_bufferoffset = 0;
8795 rsurface.modelgeneratedvertex = true;
8796 rsurface.modellightmapcolor4f = (float *)color4f;
8797 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8798 rsurface.modellightmapcolor4f_bufferoffset = 0;
8799 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8800 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8801 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8802 rsurface.modeltexcoordlightmap2f = NULL;
8803 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8804 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8805 rsurface.modelskeletalindex4ub = NULL;
8806 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8807 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8808 rsurface.modelskeletalweight4ub = NULL;
8809 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8810 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8811 rsurface.modelelement3i = (int *)element3i;
8812 rsurface.modelelement3i_indexbuffer = NULL;
8813 rsurface.modelelement3i_bufferoffset = 0;
8814 rsurface.modelelement3s = (unsigned short *)element3s;
8815 rsurface.modelelement3s_indexbuffer = NULL;
8816 rsurface.modelelement3s_bufferoffset = 0;
8817 rsurface.modellightmapoffsets = NULL;
8818 rsurface.modelsurfaces = NULL;
8819 rsurface.batchgeneratedvertex = false;
8820 rsurface.batchfirstvertex = 0;
8821 rsurface.batchnumvertices = 0;
8822 rsurface.batchfirsttriangle = 0;
8823 rsurface.batchnumtriangles = 0;
8824 rsurface.batchvertex3f = NULL;
8825 rsurface.batchvertex3f_vertexbuffer = NULL;
8826 rsurface.batchvertex3f_bufferoffset = 0;
8827 rsurface.batchsvector3f = NULL;
8828 rsurface.batchsvector3f_vertexbuffer = NULL;
8829 rsurface.batchsvector3f_bufferoffset = 0;
8830 rsurface.batchtvector3f = NULL;
8831 rsurface.batchtvector3f_vertexbuffer = NULL;
8832 rsurface.batchtvector3f_bufferoffset = 0;
8833 rsurface.batchnormal3f = NULL;
8834 rsurface.batchnormal3f_vertexbuffer = NULL;
8835 rsurface.batchnormal3f_bufferoffset = 0;
8836 rsurface.batchlightmapcolor4f = NULL;
8837 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8838 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8839 rsurface.batchtexcoordtexture2f = NULL;
8840 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8841 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8842 rsurface.batchtexcoordlightmap2f = NULL;
8843 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8844 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8845 rsurface.batchskeletalindex4ub = NULL;
8846 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8847 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8848 rsurface.batchskeletalweight4ub = NULL;
8849 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8850 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8851 rsurface.batchvertexmesh = NULL;
8852 rsurface.batchvertexmesh_vertexbuffer = NULL;
8853 rsurface.batchvertexmesh_bufferoffset = 0;
8854 rsurface.batchelement3i = NULL;
8855 rsurface.batchelement3i_indexbuffer = NULL;
8856 rsurface.batchelement3i_bufferoffset = 0;
8857 rsurface.batchelement3s = NULL;
8858 rsurface.batchelement3s_indexbuffer = NULL;
8859 rsurface.batchelement3s_bufferoffset = 0;
8860 rsurface.passcolor4f = NULL;
8861 rsurface.passcolor4f_vertexbuffer = NULL;
8862 rsurface.passcolor4f_bufferoffset = 0;
8863 rsurface.forcecurrenttextureupdate = true;
8865 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8867 if ((wantnormals || wanttangents) && !normal3f)
8869 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8870 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8872 if (wanttangents && !svector3f)
8874 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8875 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8876 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8881 float RSurf_FogPoint(const float *v)
8883 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8884 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8885 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8886 float FogHeightFade = r_refdef.fogheightfade;
8888 unsigned int fogmasktableindex;
8889 if (r_refdef.fogplaneviewabove)
8890 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8892 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8893 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8894 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8897 float RSurf_FogVertex(const float *v)
8899 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8900 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8901 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8902 float FogHeightFade = rsurface.fogheightfade;
8904 unsigned int fogmasktableindex;
8905 if (r_refdef.fogplaneviewabove)
8906 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8908 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8909 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8910 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8913 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8916 for (i = 0;i < numelements;i++)
8917 outelement3i[i] = inelement3i[i] + adjust;
8920 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8921 extern cvar_t gl_vbo;
8922 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8930 int surfacefirsttriangle;
8931 int surfacenumtriangles;
8932 int surfacefirstvertex;
8933 int surfaceendvertex;
8934 int surfacenumvertices;
8935 int batchnumsurfaces = texturenumsurfaces;
8936 int batchnumvertices;
8937 int batchnumtriangles;
8941 qboolean dynamicvertex;
8945 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8948 q3shaderinfo_deform_t *deform;
8949 const msurface_t *surface, *firstsurface;
8950 r_vertexmesh_t *vertexmesh;
8951 if (!texturenumsurfaces)
8953 // find vertex range of this surface batch
8955 firstsurface = texturesurfacelist[0];
8956 firsttriangle = firstsurface->num_firsttriangle;
8957 batchnumvertices = 0;
8958 batchnumtriangles = 0;
8959 firstvertex = endvertex = firstsurface->num_firstvertex;
8960 for (i = 0;i < texturenumsurfaces;i++)
8962 surface = texturesurfacelist[i];
8963 if (surface != firstsurface + i)
8965 surfacefirstvertex = surface->num_firstvertex;
8966 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8967 surfacenumvertices = surface->num_vertices;
8968 surfacenumtriangles = surface->num_triangles;
8969 if (firstvertex > surfacefirstvertex)
8970 firstvertex = surfacefirstvertex;
8971 if (endvertex < surfaceendvertex)
8972 endvertex = surfaceendvertex;
8973 batchnumvertices += surfacenumvertices;
8974 batchnumtriangles += surfacenumtriangles;
8977 r_refdef.stats[r_stat_batch_batches]++;
8979 r_refdef.stats[r_stat_batch_withgaps]++;
8980 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8981 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8982 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8984 // we now know the vertex range used, and if there are any gaps in it
8985 rsurface.batchfirstvertex = firstvertex;
8986 rsurface.batchnumvertices = endvertex - firstvertex;
8987 rsurface.batchfirsttriangle = firsttriangle;
8988 rsurface.batchnumtriangles = batchnumtriangles;
8990 // this variable holds flags for which properties have been updated that
8991 // may require regenerating vertexmesh array...
8994 // check if any dynamic vertex processing must occur
8995 dynamicvertex = false;
8997 // a cvar to force the dynamic vertex path to be taken, for debugging
8998 if (r_batch_debugdynamicvertexpath.integer)
9002 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9003 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9004 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9005 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9007 dynamicvertex = true;
9010 // if there is a chance of animated vertex colors, it's a dynamic batch
9011 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9015 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9016 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9017 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9018 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9020 dynamicvertex = true;
9021 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9024 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9026 switch (deform->deform)
9029 case Q3DEFORM_PROJECTIONSHADOW:
9030 case Q3DEFORM_TEXT0:
9031 case Q3DEFORM_TEXT1:
9032 case Q3DEFORM_TEXT2:
9033 case Q3DEFORM_TEXT3:
9034 case Q3DEFORM_TEXT4:
9035 case Q3DEFORM_TEXT5:
9036 case Q3DEFORM_TEXT6:
9037 case Q3DEFORM_TEXT7:
9040 case Q3DEFORM_AUTOSPRITE:
9043 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9044 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9045 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9046 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9048 dynamicvertex = true;
9049 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9050 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9052 case Q3DEFORM_AUTOSPRITE2:
9055 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9056 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9057 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9058 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9060 dynamicvertex = true;
9061 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9062 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9064 case Q3DEFORM_NORMAL:
9067 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9068 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9069 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9070 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9072 dynamicvertex = true;
9073 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9074 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9077 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9078 break; // if wavefunc is a nop, ignore this transform
9081 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9082 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9083 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9084 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9086 dynamicvertex = true;
9087 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9088 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9090 case Q3DEFORM_BULGE:
9093 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9094 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9095 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9096 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9098 dynamicvertex = true;
9099 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9100 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9103 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9104 break; // if wavefunc is a nop, ignore this transform
9107 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9108 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9109 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9110 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9112 dynamicvertex = true;
9113 batchneed |= BATCHNEED_ARRAY_VERTEX;
9114 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9118 switch(rsurface.texture->tcgen.tcgen)
9121 case Q3TCGEN_TEXTURE:
9123 case Q3TCGEN_LIGHTMAP:
9126 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9127 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9128 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9129 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9131 dynamicvertex = true;
9132 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9133 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9135 case Q3TCGEN_VECTOR:
9138 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9139 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9140 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9141 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9143 dynamicvertex = true;
9144 batchneed |= BATCHNEED_ARRAY_VERTEX;
9145 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9147 case Q3TCGEN_ENVIRONMENT:
9150 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9151 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9152 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9153 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9155 dynamicvertex = true;
9156 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9157 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9160 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9164 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9165 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9166 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9167 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9169 dynamicvertex = true;
9170 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9171 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9174 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9178 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9179 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9180 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9181 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9183 dynamicvertex = true;
9184 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9187 // when the model data has no vertex buffer (dynamic mesh), we need to
9189 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9190 batchneed |= BATCHNEED_NOGAPS;
9192 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9193 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9194 // we ensure this by treating the vertex batch as dynamic...
9195 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9199 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9200 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9201 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9202 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9204 dynamicvertex = true;
9209 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9210 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9211 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9212 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9213 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9214 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9215 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9216 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9219 // if needsupdate, we have to do a dynamic vertex batch for sure
9220 if (needsupdate & batchneed)
9224 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9225 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9226 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9227 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9229 dynamicvertex = true;
9232 // see if we need to build vertexmesh from arrays
9233 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9237 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9238 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9239 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9240 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9242 dynamicvertex = true;
9245 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9246 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9247 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9249 rsurface.batchvertex3f = rsurface.modelvertex3f;
9250 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9251 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9252 rsurface.batchsvector3f = rsurface.modelsvector3f;
9253 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9254 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9255 rsurface.batchtvector3f = rsurface.modeltvector3f;
9256 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9257 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9258 rsurface.batchnormal3f = rsurface.modelnormal3f;
9259 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9260 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9261 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9262 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9263 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9264 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9265 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9266 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9267 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9268 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9269 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9270 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9271 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9272 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9273 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9274 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9275 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9276 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9277 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9278 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9279 rsurface.batchelement3i = rsurface.modelelement3i;
9280 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9281 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9282 rsurface.batchelement3s = rsurface.modelelement3s;
9283 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9284 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9285 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9286 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9287 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9288 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9289 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9291 // if any dynamic vertex processing has to occur in software, we copy the
9292 // entire surface list together before processing to rebase the vertices
9293 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9295 // if any gaps exist and we do not have a static vertex buffer, we have to
9296 // copy the surface list together to avoid wasting upload bandwidth on the
9297 // vertices in the gaps.
9299 // if gaps exist and we have a static vertex buffer, we can choose whether
9300 // to combine the index buffer ranges into one dynamic index buffer or
9301 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9303 // in many cases the batch is reduced to one draw call.
9305 rsurface.batchmultidraw = false;
9306 rsurface.batchmultidrawnumsurfaces = 0;
9307 rsurface.batchmultidrawsurfacelist = NULL;
9311 // static vertex data, just set pointers...
9312 rsurface.batchgeneratedvertex = false;
9313 // if there are gaps, we want to build a combined index buffer,
9314 // otherwise use the original static buffer with an appropriate offset
9317 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9318 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9319 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9320 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9321 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9323 rsurface.batchmultidraw = true;
9324 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9325 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9328 // build a new triangle elements array for this batch
9329 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9330 rsurface.batchfirsttriangle = 0;
9332 for (i = 0;i < texturenumsurfaces;i++)
9334 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9335 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9336 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9337 numtriangles += surfacenumtriangles;
9339 rsurface.batchelement3i_indexbuffer = NULL;
9340 rsurface.batchelement3i_bufferoffset = 0;
9341 rsurface.batchelement3s = NULL;
9342 rsurface.batchelement3s_indexbuffer = NULL;
9343 rsurface.batchelement3s_bufferoffset = 0;
9344 if (endvertex <= 65536)
9346 // make a 16bit (unsigned short) index array if possible
9347 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9348 for (i = 0;i < numtriangles*3;i++)
9349 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9351 // upload buffer data for the copytriangles batch
9352 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9354 if (rsurface.batchelement3s)
9355 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9356 else if (rsurface.batchelement3i)
9357 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9362 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9363 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9364 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9365 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9370 // something needs software processing, do it for real...
9371 // we only directly handle separate array data in this case and then
9372 // generate interleaved data if needed...
9373 rsurface.batchgeneratedvertex = true;
9374 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9375 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9376 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9377 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9379 // now copy the vertex data into a combined array and make an index array
9380 // (this is what Quake3 does all the time)
9381 // we also apply any skeletal animation here that would have been done in
9382 // the vertex shader, because most of the dynamic vertex animation cases
9383 // need actual vertex positions and normals
9384 //if (dynamicvertex)
9386 rsurface.batchvertexmesh = NULL;
9387 rsurface.batchvertexmesh_vertexbuffer = NULL;
9388 rsurface.batchvertexmesh_bufferoffset = 0;
9389 rsurface.batchvertex3f = NULL;
9390 rsurface.batchvertex3f_vertexbuffer = NULL;
9391 rsurface.batchvertex3f_bufferoffset = 0;
9392 rsurface.batchsvector3f = NULL;
9393 rsurface.batchsvector3f_vertexbuffer = NULL;
9394 rsurface.batchsvector3f_bufferoffset = 0;
9395 rsurface.batchtvector3f = NULL;
9396 rsurface.batchtvector3f_vertexbuffer = NULL;
9397 rsurface.batchtvector3f_bufferoffset = 0;
9398 rsurface.batchnormal3f = NULL;
9399 rsurface.batchnormal3f_vertexbuffer = NULL;
9400 rsurface.batchnormal3f_bufferoffset = 0;
9401 rsurface.batchlightmapcolor4f = NULL;
9402 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9403 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9404 rsurface.batchtexcoordtexture2f = NULL;
9405 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9406 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9407 rsurface.batchtexcoordlightmap2f = NULL;
9408 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9409 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9410 rsurface.batchskeletalindex4ub = NULL;
9411 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9412 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9413 rsurface.batchskeletalweight4ub = NULL;
9414 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9415 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9416 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9417 rsurface.batchelement3i_indexbuffer = NULL;
9418 rsurface.batchelement3i_bufferoffset = 0;
9419 rsurface.batchelement3s = NULL;
9420 rsurface.batchelement3s_indexbuffer = NULL;
9421 rsurface.batchelement3s_bufferoffset = 0;
9422 rsurface.batchskeletaltransform3x4buffer = NULL;
9423 rsurface.batchskeletaltransform3x4offset = 0;
9424 rsurface.batchskeletaltransform3x4size = 0;
9425 // we'll only be setting up certain arrays as needed
9426 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9427 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9428 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9429 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9430 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9431 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9432 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9434 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9435 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9437 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9438 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9439 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9440 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9441 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9442 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9443 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9445 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9446 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9450 for (i = 0;i < texturenumsurfaces;i++)
9452 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9453 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9454 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9455 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9456 // copy only the data requested
9457 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9458 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9459 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9461 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9463 if (rsurface.batchvertex3f)
9464 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9466 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9468 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9470 if (rsurface.modelnormal3f)
9471 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9473 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9475 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9477 if (rsurface.modelsvector3f)
9479 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9480 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9484 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9485 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9488 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9490 if (rsurface.modellightmapcolor4f)
9491 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9493 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9495 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9497 if (rsurface.modeltexcoordtexture2f)
9498 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9500 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9502 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9504 if (rsurface.modeltexcoordlightmap2f)
9505 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9507 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9509 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9511 if (rsurface.modelskeletalindex4ub)
9513 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9514 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9518 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9519 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9520 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9521 for (j = 0;j < surfacenumvertices;j++)
9526 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9527 numvertices += surfacenumvertices;
9528 numtriangles += surfacenumtriangles;
9531 // generate a 16bit index array as well if possible
9532 // (in general, dynamic batches fit)
9533 if (numvertices <= 65536)
9535 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9536 for (i = 0;i < numtriangles*3;i++)
9537 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9540 // since we've copied everything, the batch now starts at 0
9541 rsurface.batchfirstvertex = 0;
9542 rsurface.batchnumvertices = batchnumvertices;
9543 rsurface.batchfirsttriangle = 0;
9544 rsurface.batchnumtriangles = batchnumtriangles;
9547 // apply skeletal animation that would have been done in the vertex shader
9548 if (rsurface.batchskeletaltransform3x4)
9550 const unsigned char *si;
9551 const unsigned char *sw;
9553 const float *b = rsurface.batchskeletaltransform3x4;
9554 float *vp, *vs, *vt, *vn;
9556 float m[3][4], n[3][4];
9557 float tp[3], ts[3], tt[3], tn[3];
9558 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9559 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9560 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9561 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9562 si = rsurface.batchskeletalindex4ub;
9563 sw = rsurface.batchskeletalweight4ub;
9564 vp = rsurface.batchvertex3f;
9565 vs = rsurface.batchsvector3f;
9566 vt = rsurface.batchtvector3f;
9567 vn = rsurface.batchnormal3f;
9568 memset(m[0], 0, sizeof(m));
9569 memset(n[0], 0, sizeof(n));
9570 for (i = 0;i < batchnumvertices;i++)
9572 t[0] = b + si[0]*12;
9575 // common case - only one matrix
9589 else if (sw[2] + sw[3])
9592 t[1] = b + si[1]*12;
9593 t[2] = b + si[2]*12;
9594 t[3] = b + si[3]*12;
9595 w[0] = sw[0] * (1.0f / 255.0f);
9596 w[1] = sw[1] * (1.0f / 255.0f);
9597 w[2] = sw[2] * (1.0f / 255.0f);
9598 w[3] = sw[3] * (1.0f / 255.0f);
9599 // blend the matrices
9600 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9601 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9602 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9603 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9604 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9605 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9606 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9607 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9608 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9609 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9610 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9611 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9616 t[1] = b + si[1]*12;
9617 w[0] = sw[0] * (1.0f / 255.0f);
9618 w[1] = sw[1] * (1.0f / 255.0f);
9619 // blend the matrices
9620 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9621 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9622 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9623 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9624 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9625 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9626 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9627 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9628 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9629 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9630 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9631 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9635 // modify the vertex
9637 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9638 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9639 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9643 // the normal transformation matrix is a set of cross products...
9644 CrossProduct(m[1], m[2], n[0]);
9645 CrossProduct(m[2], m[0], n[1]);
9646 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9648 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9649 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9650 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9651 VectorNormalize(vn);
9656 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9657 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9658 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9659 VectorNormalize(vs);
9662 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9663 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9664 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9665 VectorNormalize(vt);
9670 rsurface.batchskeletaltransform3x4 = NULL;
9671 rsurface.batchskeletalnumtransforms = 0;
9674 // q1bsp surfaces rendered in vertex color mode have to have colors
9675 // calculated based on lightstyles
9676 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9678 // generate color arrays for the surfaces in this list
9683 const unsigned char *lm;
9684 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9685 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9686 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9688 for (i = 0;i < texturenumsurfaces;i++)
9690 surface = texturesurfacelist[i];
9691 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9692 surfacenumvertices = surface->num_vertices;
9693 if (surface->lightmapinfo->samples)
9695 for (j = 0;j < surfacenumvertices;j++)
9697 lm = surface->lightmapinfo->samples + offsets[j];
9698 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9699 VectorScale(lm, scale, c);
9700 if (surface->lightmapinfo->styles[1] != 255)
9702 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9704 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9705 VectorMA(c, scale, lm, c);
9706 if (surface->lightmapinfo->styles[2] != 255)
9709 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9710 VectorMA(c, scale, lm, c);
9711 if (surface->lightmapinfo->styles[3] != 255)
9714 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9715 VectorMA(c, scale, lm, c);
9722 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);
9728 for (j = 0;j < surfacenumvertices;j++)
9730 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9737 // if vertices are deformed (sprite flares and things in maps, possibly
9738 // water waves, bulges and other deformations), modify the copied vertices
9740 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9742 switch (deform->deform)
9745 case Q3DEFORM_PROJECTIONSHADOW:
9746 case Q3DEFORM_TEXT0:
9747 case Q3DEFORM_TEXT1:
9748 case Q3DEFORM_TEXT2:
9749 case Q3DEFORM_TEXT3:
9750 case Q3DEFORM_TEXT4:
9751 case Q3DEFORM_TEXT5:
9752 case Q3DEFORM_TEXT6:
9753 case Q3DEFORM_TEXT7:
9756 case Q3DEFORM_AUTOSPRITE:
9757 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9758 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9759 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9760 VectorNormalize(newforward);
9761 VectorNormalize(newright);
9762 VectorNormalize(newup);
9763 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9764 // rsurface.batchvertex3f_vertexbuffer = NULL;
9765 // rsurface.batchvertex3f_bufferoffset = 0;
9766 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9767 // rsurface.batchsvector3f_vertexbuffer = NULL;
9768 // rsurface.batchsvector3f_bufferoffset = 0;
9769 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9770 // rsurface.batchtvector3f_vertexbuffer = NULL;
9771 // rsurface.batchtvector3f_bufferoffset = 0;
9772 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9773 // rsurface.batchnormal3f_vertexbuffer = NULL;
9774 // rsurface.batchnormal3f_bufferoffset = 0;
9775 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9776 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9777 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9778 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9779 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);
9780 // a single autosprite surface can contain multiple sprites...
9781 for (j = 0;j < batchnumvertices - 3;j += 4)
9783 VectorClear(center);
9784 for (i = 0;i < 4;i++)
9785 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9786 VectorScale(center, 0.25f, center);
9787 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9788 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9789 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9790 for (i = 0;i < 4;i++)
9792 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9793 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9796 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9797 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9798 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);
9800 case Q3DEFORM_AUTOSPRITE2:
9801 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9802 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9803 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9804 VectorNormalize(newforward);
9805 VectorNormalize(newright);
9806 VectorNormalize(newup);
9807 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9808 // rsurface.batchvertex3f_vertexbuffer = NULL;
9809 // rsurface.batchvertex3f_bufferoffset = 0;
9811 const float *v1, *v2;
9821 memset(shortest, 0, sizeof(shortest));
9822 // a single autosprite surface can contain multiple sprites...
9823 for (j = 0;j < batchnumvertices - 3;j += 4)
9825 VectorClear(center);
9826 for (i = 0;i < 4;i++)
9827 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9828 VectorScale(center, 0.25f, center);
9829 // find the two shortest edges, then use them to define the
9830 // axis vectors for rotating around the central axis
9831 for (i = 0;i < 6;i++)
9833 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9834 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9835 l = VectorDistance2(v1, v2);
9836 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9838 l += (1.0f / 1024.0f);
9839 if (shortest[0].length2 > l || i == 0)
9841 shortest[1] = shortest[0];
9842 shortest[0].length2 = l;
9843 shortest[0].v1 = v1;
9844 shortest[0].v2 = v2;
9846 else if (shortest[1].length2 > l || i == 1)
9848 shortest[1].length2 = l;
9849 shortest[1].v1 = v1;
9850 shortest[1].v2 = v2;
9853 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9854 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9855 // this calculates the right vector from the shortest edge
9856 // and the up vector from the edge midpoints
9857 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9858 VectorNormalize(right);
9859 VectorSubtract(end, start, up);
9860 VectorNormalize(up);
9861 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9862 VectorSubtract(rsurface.localvieworigin, center, forward);
9863 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9864 VectorNegate(forward, forward);
9865 VectorReflect(forward, 0, up, forward);
9866 VectorNormalize(forward);
9867 CrossProduct(up, forward, newright);
9868 VectorNormalize(newright);
9869 // rotate the quad around the up axis vector, this is made
9870 // especially easy by the fact we know the quad is flat,
9871 // so we only have to subtract the center position and
9872 // measure distance along the right vector, and then
9873 // multiply that by the newright vector and add back the
9875 // we also need to subtract the old position to undo the
9876 // displacement from the center, which we do with a
9877 // DotProduct, the subtraction/addition of center is also
9878 // optimized into DotProducts here
9879 l = DotProduct(right, center);
9880 for (i = 0;i < 4;i++)
9882 v1 = rsurface.batchvertex3f + 3*(j+i);
9883 f = DotProduct(right, v1) - l;
9884 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9888 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9890 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9891 // rsurface.batchnormal3f_vertexbuffer = NULL;
9892 // rsurface.batchnormal3f_bufferoffset = 0;
9893 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9895 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9897 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9898 // rsurface.batchsvector3f_vertexbuffer = NULL;
9899 // rsurface.batchsvector3f_bufferoffset = 0;
9900 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9901 // rsurface.batchtvector3f_vertexbuffer = NULL;
9902 // rsurface.batchtvector3f_bufferoffset = 0;
9903 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);
9906 case Q3DEFORM_NORMAL:
9907 // deform the normals to make reflections wavey
9908 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9909 rsurface.batchnormal3f_vertexbuffer = NULL;
9910 rsurface.batchnormal3f_bufferoffset = 0;
9911 for (j = 0;j < batchnumvertices;j++)
9914 float *normal = rsurface.batchnormal3f + 3*j;
9915 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9916 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9917 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9918 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9919 VectorNormalize(normal);
9921 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9923 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9924 // rsurface.batchsvector3f_vertexbuffer = NULL;
9925 // rsurface.batchsvector3f_bufferoffset = 0;
9926 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9927 // rsurface.batchtvector3f_vertexbuffer = NULL;
9928 // rsurface.batchtvector3f_bufferoffset = 0;
9929 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);
9933 // deform vertex array to make wavey water and flags and such
9934 waveparms[0] = deform->waveparms[0];
9935 waveparms[1] = deform->waveparms[1];
9936 waveparms[2] = deform->waveparms[2];
9937 waveparms[3] = deform->waveparms[3];
9938 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9939 break; // if wavefunc is a nop, don't make a dynamic vertex array
9940 // this is how a divisor of vertex influence on deformation
9941 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9942 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9943 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9944 // rsurface.batchvertex3f_vertexbuffer = NULL;
9945 // rsurface.batchvertex3f_bufferoffset = 0;
9946 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9947 // rsurface.batchnormal3f_vertexbuffer = NULL;
9948 // rsurface.batchnormal3f_bufferoffset = 0;
9949 for (j = 0;j < batchnumvertices;j++)
9951 // if the wavefunc depends on time, evaluate it per-vertex
9954 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9955 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9957 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9959 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9960 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9961 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9963 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9964 // rsurface.batchsvector3f_vertexbuffer = NULL;
9965 // rsurface.batchsvector3f_bufferoffset = 0;
9966 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9967 // rsurface.batchtvector3f_vertexbuffer = NULL;
9968 // rsurface.batchtvector3f_bufferoffset = 0;
9969 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);
9972 case Q3DEFORM_BULGE:
9973 // deform vertex array to make the surface have moving bulges
9974 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9975 // rsurface.batchvertex3f_vertexbuffer = NULL;
9976 // rsurface.batchvertex3f_bufferoffset = 0;
9977 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9978 // rsurface.batchnormal3f_vertexbuffer = NULL;
9979 // rsurface.batchnormal3f_bufferoffset = 0;
9980 for (j = 0;j < batchnumvertices;j++)
9982 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9983 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9985 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9986 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9987 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9989 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9990 // rsurface.batchsvector3f_vertexbuffer = NULL;
9991 // rsurface.batchsvector3f_bufferoffset = 0;
9992 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9993 // rsurface.batchtvector3f_vertexbuffer = NULL;
9994 // rsurface.batchtvector3f_bufferoffset = 0;
9995 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);
9999 // deform vertex array
10000 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10001 break; // if wavefunc is a nop, don't make a dynamic vertex array
10002 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10003 VectorScale(deform->parms, scale, waveparms);
10004 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10005 // rsurface.batchvertex3f_vertexbuffer = NULL;
10006 // rsurface.batchvertex3f_bufferoffset = 0;
10007 for (j = 0;j < batchnumvertices;j++)
10008 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10013 // generate texcoords based on the chosen texcoord source
10014 switch(rsurface.texture->tcgen.tcgen)
10017 case Q3TCGEN_TEXTURE:
10019 case Q3TCGEN_LIGHTMAP:
10020 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10021 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10022 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10023 if (rsurface.batchtexcoordlightmap2f)
10024 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10026 case Q3TCGEN_VECTOR:
10027 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10028 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10029 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10030 for (j = 0;j < batchnumvertices;j++)
10032 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10033 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10036 case Q3TCGEN_ENVIRONMENT:
10037 // make environment reflections using a spheremap
10038 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10039 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10040 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10041 for (j = 0;j < batchnumvertices;j++)
10043 // identical to Q3A's method, but executed in worldspace so
10044 // carried models can be shiny too
10046 float viewer[3], d, reflected[3], worldreflected[3];
10048 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10049 // VectorNormalize(viewer);
10051 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10053 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10054 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10055 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10056 // note: this is proportinal to viewer, so we can normalize later
10058 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10059 VectorNormalize(worldreflected);
10061 // note: this sphere map only uses world x and z!
10062 // so positive and negative y will LOOK THE SAME.
10063 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10064 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10068 // the only tcmod that needs software vertex processing is turbulent, so
10069 // check for it here and apply the changes if needed
10070 // and we only support that as the first one
10071 // (handling a mixture of turbulent and other tcmods would be problematic
10072 // without punting it entirely to a software path)
10073 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10075 amplitude = rsurface.texture->tcmods[0].parms[1];
10076 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10077 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10078 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10079 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10080 for (j = 0;j < batchnumvertices;j++)
10082 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);
10083 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10087 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10089 // convert the modified arrays to vertex structs
10090 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10091 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10092 // rsurface.batchvertexmesh_bufferoffset = 0;
10093 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10094 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10095 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10096 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10097 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10098 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10099 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10101 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10103 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10104 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10107 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10108 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10109 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10110 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10111 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10112 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10113 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10114 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10115 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10116 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10118 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10120 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10121 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10126 // upload buffer data for the dynamic batch
10127 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10129 if (rsurface.batchvertexmesh)
10130 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10133 if (rsurface.batchvertex3f)
10134 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10135 if (rsurface.batchsvector3f)
10136 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10137 if (rsurface.batchtvector3f)
10138 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10139 if (rsurface.batchnormal3f)
10140 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10141 if (rsurface.batchlightmapcolor4f)
10142 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10143 if (rsurface.batchtexcoordtexture2f)
10144 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10145 if (rsurface.batchtexcoordlightmap2f)
10146 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10147 if (rsurface.batchskeletalindex4ub)
10148 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10149 if (rsurface.batchskeletalweight4ub)
10150 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10152 if (rsurface.batchelement3s)
10153 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10154 else if (rsurface.batchelement3i)
10155 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10159 void RSurf_DrawBatch(void)
10161 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10162 // through the pipeline, killing it earlier in the pipeline would have
10163 // per-surface overhead rather than per-batch overhead, so it's best to
10164 // reject it here, before it hits glDraw.
10165 if (rsurface.batchnumtriangles == 0)
10168 // batch debugging code
10169 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10175 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10176 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10179 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10181 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10183 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10184 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);
10191 if (rsurface.batchmultidraw)
10193 // issue multiple draws rather than copying index data
10194 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10195 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10196 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10197 for (i = 0;i < numsurfaces;)
10199 // combine consecutive surfaces as one draw
10200 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10201 if (surfacelist[j] != surfacelist[k] + 1)
10203 firstvertex = surfacelist[i]->num_firstvertex;
10204 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10205 firsttriangle = surfacelist[i]->num_firsttriangle;
10206 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10207 R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
10213 // there is only one consecutive run of index data (may have been combined)
10214 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);
10218 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10220 // pick the closest matching water plane
10221 int planeindex, vertexindex, bestplaneindex = -1;
10225 r_waterstate_waterplane_t *p;
10226 qboolean prepared = false;
10228 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10230 if(p->camera_entity != rsurface.texture->camera_entity)
10235 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10237 if(rsurface.batchnumvertices == 0)
10240 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10242 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10243 d += fabs(PlaneDiff(vert, &p->plane));
10245 if (bestd > d || bestplaneindex < 0)
10248 bestplaneindex = planeindex;
10251 return bestplaneindex;
10252 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10253 // this situation though, as it might be better to render single larger
10254 // batches with useless stuff (backface culled for example) than to
10255 // render multiple smaller batches
10258 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10261 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10262 rsurface.passcolor4f_vertexbuffer = 0;
10263 rsurface.passcolor4f_bufferoffset = 0;
10264 for (i = 0;i < rsurface.batchnumvertices;i++)
10265 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10268 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10275 if (rsurface.passcolor4f)
10277 // generate color arrays
10278 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10279 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10280 rsurface.passcolor4f_vertexbuffer = 0;
10281 rsurface.passcolor4f_bufferoffset = 0;
10282 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)
10284 f = RSurf_FogVertex(v);
10293 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10294 rsurface.passcolor4f_vertexbuffer = 0;
10295 rsurface.passcolor4f_bufferoffset = 0;
10296 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10298 f = RSurf_FogVertex(v);
10307 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10314 if (!rsurface.passcolor4f)
10316 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10317 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10318 rsurface.passcolor4f_vertexbuffer = 0;
10319 rsurface.passcolor4f_bufferoffset = 0;
10320 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)
10322 f = RSurf_FogVertex(v);
10323 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10324 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10325 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10330 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10335 if (!rsurface.passcolor4f)
10337 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10338 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10339 rsurface.passcolor4f_vertexbuffer = 0;
10340 rsurface.passcolor4f_bufferoffset = 0;
10341 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10350 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10355 if (!rsurface.passcolor4f)
10357 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10358 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10359 rsurface.passcolor4f_vertexbuffer = 0;
10360 rsurface.passcolor4f_bufferoffset = 0;
10361 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10363 c2[0] = c[0] + r_refdef.scene.ambient;
10364 c2[1] = c[1] + r_refdef.scene.ambient;
10365 c2[2] = c[2] + r_refdef.scene.ambient;
10370 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10373 rsurface.passcolor4f = NULL;
10374 rsurface.passcolor4f_vertexbuffer = 0;
10375 rsurface.passcolor4f_bufferoffset = 0;
10376 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10377 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10378 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10379 GL_Color(r, g, b, a);
10380 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10381 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10382 R_Mesh_TexMatrix(0, NULL);
10386 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10388 // TODO: optimize applyfog && applycolor case
10389 // just apply fog if necessary, and tint the fog color array if necessary
10390 rsurface.passcolor4f = NULL;
10391 rsurface.passcolor4f_vertexbuffer = 0;
10392 rsurface.passcolor4f_bufferoffset = 0;
10393 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10394 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10395 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10396 GL_Color(r, g, b, a);
10400 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10403 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10404 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10405 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10406 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10407 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10408 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10409 GL_Color(r, g, b, a);
10413 static void RSurf_DrawBatch_GL11_ClampColor(void)
10418 if (!rsurface.passcolor4f)
10420 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10422 c2[0] = bound(0.0f, c1[0], 1.0f);
10423 c2[1] = bound(0.0f, c1[1], 1.0f);
10424 c2[2] = bound(0.0f, c1[2], 1.0f);
10425 c2[3] = bound(0.0f, c1[3], 1.0f);
10429 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10439 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10440 rsurface.passcolor4f_vertexbuffer = 0;
10441 rsurface.passcolor4f_bufferoffset = 0;
10442 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)
10444 f = -DotProduct(r_refdef.view.forward, n);
10446 f = f * 0.85 + 0.15; // work around so stuff won't get black
10447 f *= r_refdef.lightmapintensity;
10448 Vector4Set(c, f, f, f, 1);
10452 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10454 RSurf_DrawBatch_GL11_ApplyFakeLight();
10455 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10456 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10457 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10458 GL_Color(r, g, b, a);
10462 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10470 vec3_t ambientcolor;
10471 vec3_t diffusecolor;
10475 VectorCopy(rsurface.modellight_lightdir, lightdir);
10476 f = 0.5f * r_refdef.lightmapintensity;
10477 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10478 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10479 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10480 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10481 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10482 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10484 if (VectorLength2(diffusecolor) > 0)
10486 // q3-style directional shading
10487 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10488 rsurface.passcolor4f_vertexbuffer = 0;
10489 rsurface.passcolor4f_bufferoffset = 0;
10490 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)
10492 if ((f = DotProduct(n, lightdir)) > 0)
10493 VectorMA(ambientcolor, f, diffusecolor, c);
10495 VectorCopy(ambientcolor, c);
10502 *applycolor = false;
10506 *r = ambientcolor[0];
10507 *g = ambientcolor[1];
10508 *b = ambientcolor[2];
10509 rsurface.passcolor4f = NULL;
10510 rsurface.passcolor4f_vertexbuffer = 0;
10511 rsurface.passcolor4f_bufferoffset = 0;
10515 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10517 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10518 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10519 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10520 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10521 GL_Color(r, g, b, a);
10525 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10533 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10534 rsurface.passcolor4f_vertexbuffer = 0;
10535 rsurface.passcolor4f_bufferoffset = 0;
10537 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10539 f = 1 - RSurf_FogVertex(v);
10547 void RSurf_SetupDepthAndCulling(void)
10549 // submodels are biased to avoid z-fighting with world surfaces that they
10550 // may be exactly overlapping (avoids z-fighting artifacts on certain
10551 // doors and things in Quake maps)
10552 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10553 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10554 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10555 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10558 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10560 // transparent sky would be ridiculous
10561 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10563 R_SetupShader_Generic_NoTexture(false, false);
10564 skyrenderlater = true;
10565 RSurf_SetupDepthAndCulling();
10566 GL_DepthMask(true);
10567 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10568 // skymasking on them, and Quake3 never did sky masking (unlike
10569 // software Quake and software Quake2), so disable the sky masking
10570 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10571 // and skymasking also looks very bad when noclipping outside the
10572 // level, so don't use it then either.
10573 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10575 R_Mesh_ResetTextureState();
10576 if (skyrendermasked)
10578 R_SetupShader_DepthOrShadow(false, false, false);
10579 // depth-only (masking)
10580 GL_ColorMask(0,0,0,0);
10581 // just to make sure that braindead drivers don't draw
10582 // anything despite that colormask...
10583 GL_BlendFunc(GL_ZERO, GL_ONE);
10584 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10585 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10589 R_SetupShader_Generic_NoTexture(false, false);
10591 GL_BlendFunc(GL_ONE, GL_ZERO);
10592 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10593 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10594 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10597 if (skyrendermasked)
10598 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10600 R_Mesh_ResetTextureState();
10601 GL_Color(1, 1, 1, 1);
10604 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10605 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10606 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10608 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10612 // render screenspace normalmap to texture
10613 GL_DepthMask(true);
10614 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10619 // bind lightmap texture
10621 // water/refraction/reflection/camera surfaces have to be handled specially
10622 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10624 int start, end, startplaneindex;
10625 for (start = 0;start < texturenumsurfaces;start = end)
10627 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10628 if(startplaneindex < 0)
10630 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10631 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10635 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10637 // now that we have a batch using the same planeindex, render it
10638 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10640 // render water or distortion background
10641 GL_DepthMask(true);
10642 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10644 // blend surface on top
10645 GL_DepthMask(false);
10646 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10649 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10651 // render surface with reflection texture as input
10652 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10653 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10660 // render surface batch normally
10661 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10662 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);
10666 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10668 // OpenGL 1.3 path - anything not completely ancient
10669 qboolean applycolor;
10672 const texturelayer_t *layer;
10673 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);
10674 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10676 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10679 int layertexrgbscale;
10680 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10682 if (layerindex == 0)
10683 GL_AlphaTest(true);
10686 GL_AlphaTest(false);
10687 GL_DepthFunc(GL_EQUAL);
10690 GL_DepthMask(layer->depthmask && writedepth);
10691 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10692 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10694 layertexrgbscale = 4;
10695 VectorScale(layer->color, 0.25f, layercolor);
10697 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10699 layertexrgbscale = 2;
10700 VectorScale(layer->color, 0.5f, layercolor);
10704 layertexrgbscale = 1;
10705 VectorScale(layer->color, 1.0f, layercolor);
10707 layercolor[3] = layer->color[3];
10708 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10709 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10710 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10711 switch (layer->type)
10713 case TEXTURELAYERTYPE_LITTEXTURE:
10714 // single-pass lightmapped texture with 2x rgbscale
10715 R_Mesh_TexBind(0, r_texture_white);
10716 R_Mesh_TexMatrix(0, NULL);
10717 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10718 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10719 R_Mesh_TexBind(1, layer->texture);
10720 R_Mesh_TexMatrix(1, &layer->texmatrix);
10721 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10722 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10723 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10724 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10725 else if (FAKELIGHT_ENABLED)
10726 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10727 else if (rsurface.uselightmaptexture)
10728 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10730 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10732 case TEXTURELAYERTYPE_TEXTURE:
10733 // singletexture unlit texture with transparency support
10734 R_Mesh_TexBind(0, layer->texture);
10735 R_Mesh_TexMatrix(0, &layer->texmatrix);
10736 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10737 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10738 R_Mesh_TexBind(1, 0);
10739 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10740 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10742 case TEXTURELAYERTYPE_FOG:
10743 // singletexture fogging
10744 if (layer->texture)
10746 R_Mesh_TexBind(0, layer->texture);
10747 R_Mesh_TexMatrix(0, &layer->texmatrix);
10748 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10749 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10753 R_Mesh_TexBind(0, 0);
10754 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10756 R_Mesh_TexBind(1, 0);
10757 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10758 // generate a color array for the fog pass
10759 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10760 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10764 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10767 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10769 GL_DepthFunc(GL_LEQUAL);
10770 GL_AlphaTest(false);
10774 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10776 // OpenGL 1.1 - crusty old voodoo path
10779 const texturelayer_t *layer;
10780 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);
10781 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10783 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10785 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10787 if (layerindex == 0)
10788 GL_AlphaTest(true);
10791 GL_AlphaTest(false);
10792 GL_DepthFunc(GL_EQUAL);
10795 GL_DepthMask(layer->depthmask && writedepth);
10796 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10797 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10798 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10799 switch (layer->type)
10801 case TEXTURELAYERTYPE_LITTEXTURE:
10802 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10804 // two-pass lit texture with 2x rgbscale
10805 // first the lightmap pass
10806 R_Mesh_TexBind(0, r_texture_white);
10807 R_Mesh_TexMatrix(0, NULL);
10808 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10809 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10810 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10811 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10812 else if (FAKELIGHT_ENABLED)
10813 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10814 else if (rsurface.uselightmaptexture)
10815 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10817 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10818 // then apply the texture to it
10819 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10820 R_Mesh_TexBind(0, layer->texture);
10821 R_Mesh_TexMatrix(0, &layer->texmatrix);
10822 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10823 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10824 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);
10828 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10829 R_Mesh_TexBind(0, layer->texture);
10830 R_Mesh_TexMatrix(0, &layer->texmatrix);
10831 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10832 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10833 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10834 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);
10835 else if (FAKELIGHT_ENABLED)
10836 RSurf_DrawBatch_GL11_FakeLight(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);
10838 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);
10841 case TEXTURELAYERTYPE_TEXTURE:
10842 // singletexture unlit texture with transparency support
10843 R_Mesh_TexBind(0, layer->texture);
10844 R_Mesh_TexMatrix(0, &layer->texmatrix);
10845 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10846 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10847 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);
10849 case TEXTURELAYERTYPE_FOG:
10850 // singletexture fogging
10851 if (layer->texture)
10853 R_Mesh_TexBind(0, layer->texture);
10854 R_Mesh_TexMatrix(0, &layer->texmatrix);
10855 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10856 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10860 R_Mesh_TexBind(0, 0);
10861 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10863 // generate a color array for the fog pass
10864 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10865 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10869 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10872 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10874 GL_DepthFunc(GL_LEQUAL);
10875 GL_AlphaTest(false);
10879 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10883 r_vertexgeneric_t *batchvertex;
10886 // R_Mesh_ResetTextureState();
10887 R_SetupShader_Generic_NoTexture(false, false);
10889 if(rsurface.texture && rsurface.texture->currentskinframe)
10891 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10892 c[3] *= rsurface.texture->currentalpha;
10902 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10904 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10905 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10906 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10909 // brighten it up (as texture value 127 means "unlit")
10910 c[0] *= 2 * r_refdef.view.colorscale;
10911 c[1] *= 2 * r_refdef.view.colorscale;
10912 c[2] *= 2 * r_refdef.view.colorscale;
10914 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10915 c[3] *= r_wateralpha.value;
10917 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10919 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10920 GL_DepthMask(false);
10922 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10924 GL_BlendFunc(GL_ONE, GL_ONE);
10925 GL_DepthMask(false);
10927 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10929 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10930 GL_DepthMask(false);
10932 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10934 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10935 GL_DepthMask(false);
10939 GL_BlendFunc(GL_ONE, GL_ZERO);
10940 GL_DepthMask(writedepth);
10943 if (r_showsurfaces.integer == 3)
10945 rsurface.passcolor4f = NULL;
10947 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10949 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10951 rsurface.passcolor4f = NULL;
10952 rsurface.passcolor4f_vertexbuffer = 0;
10953 rsurface.passcolor4f_bufferoffset = 0;
10955 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10957 qboolean applycolor = true;
10960 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10962 r_refdef.lightmapintensity = 1;
10963 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10964 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10966 else if (FAKELIGHT_ENABLED)
10968 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10970 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10971 RSurf_DrawBatch_GL11_ApplyFakeLight();
10972 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10976 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10978 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10979 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10980 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10983 if(!rsurface.passcolor4f)
10984 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10986 RSurf_DrawBatch_GL11_ApplyAmbient();
10987 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10988 if(r_refdef.fogenabled)
10989 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10990 RSurf_DrawBatch_GL11_ClampColor();
10992 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10993 R_SetupShader_Generic_NoTexture(false, false);
10996 else if (!r_refdef.view.showdebug)
10998 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10999 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11000 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11002 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11003 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11005 R_Mesh_PrepareVertices_Generic_Unlock();
11008 else if (r_showsurfaces.integer == 4)
11010 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11011 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11012 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11014 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11015 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11016 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11018 R_Mesh_PrepareVertices_Generic_Unlock();
11021 else if (r_showsurfaces.integer == 2)
11024 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11025 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11026 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11028 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11029 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11030 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11031 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11032 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11033 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11034 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11036 R_Mesh_PrepareVertices_Generic_Unlock();
11037 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11041 int texturesurfaceindex;
11043 const msurface_t *surface;
11044 float surfacecolor4f[4];
11045 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11046 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11048 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11050 surface = texturesurfacelist[texturesurfaceindex];
11051 k = (int)(((size_t)surface) / sizeof(msurface_t));
11052 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11053 for (j = 0;j < surface->num_vertices;j++)
11055 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11056 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11060 R_Mesh_PrepareVertices_Generic_Unlock();
11065 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11068 RSurf_SetupDepthAndCulling();
11069 if (r_showsurfaces.integer)
11071 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11074 switch (vid.renderpath)
11076 case RENDERPATH_GL20:
11077 case RENDERPATH_D3D9:
11078 case RENDERPATH_D3D10:
11079 case RENDERPATH_D3D11:
11080 case RENDERPATH_SOFT:
11081 case RENDERPATH_GLES2:
11082 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11084 case RENDERPATH_GL13:
11085 case RENDERPATH_GLES1:
11086 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11088 case RENDERPATH_GL11:
11089 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11095 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11098 RSurf_SetupDepthAndCulling();
11099 if (r_showsurfaces.integer)
11101 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11104 switch (vid.renderpath)
11106 case RENDERPATH_GL20:
11107 case RENDERPATH_D3D9:
11108 case RENDERPATH_D3D10:
11109 case RENDERPATH_D3D11:
11110 case RENDERPATH_SOFT:
11111 case RENDERPATH_GLES2:
11112 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11114 case RENDERPATH_GL13:
11115 case RENDERPATH_GLES1:
11116 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11118 case RENDERPATH_GL11:
11119 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11125 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11128 int texturenumsurfaces, endsurface;
11129 texture_t *texture;
11130 const msurface_t *surface;
11131 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11133 // if the model is static it doesn't matter what value we give for
11134 // wantnormals and wanttangents, so this logic uses only rules applicable
11135 // to a model, knowing that they are meaningless otherwise
11136 if (ent == r_refdef.scene.worldentity)
11137 RSurf_ActiveWorldEntity();
11138 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11139 RSurf_ActiveModelEntity(ent, false, false, false);
11142 switch (vid.renderpath)
11144 case RENDERPATH_GL20:
11145 case RENDERPATH_D3D9:
11146 case RENDERPATH_D3D10:
11147 case RENDERPATH_D3D11:
11148 case RENDERPATH_SOFT:
11149 case RENDERPATH_GLES2:
11150 RSurf_ActiveModelEntity(ent, true, true, false);
11152 case RENDERPATH_GL11:
11153 case RENDERPATH_GL13:
11154 case RENDERPATH_GLES1:
11155 RSurf_ActiveModelEntity(ent, true, false, false);
11160 if (r_transparentdepthmasking.integer)
11162 qboolean setup = false;
11163 for (i = 0;i < numsurfaces;i = j)
11166 surface = rsurface.modelsurfaces + surfacelist[i];
11167 texture = surface->texture;
11168 rsurface.texture = R_GetCurrentTexture(texture);
11169 rsurface.lightmaptexture = NULL;
11170 rsurface.deluxemaptexture = NULL;
11171 rsurface.uselightmaptexture = false;
11172 // scan ahead until we find a different texture
11173 endsurface = min(i + 1024, numsurfaces);
11174 texturenumsurfaces = 0;
11175 texturesurfacelist[texturenumsurfaces++] = surface;
11176 for (;j < endsurface;j++)
11178 surface = rsurface.modelsurfaces + surfacelist[j];
11179 if (texture != surface->texture)
11181 texturesurfacelist[texturenumsurfaces++] = surface;
11183 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11185 // render the range of surfaces as depth
11189 GL_ColorMask(0,0,0,0);
11191 GL_DepthTest(true);
11192 GL_BlendFunc(GL_ONE, GL_ZERO);
11193 GL_DepthMask(true);
11194 // R_Mesh_ResetTextureState();
11196 RSurf_SetupDepthAndCulling();
11197 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11198 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11199 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11203 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11206 for (i = 0;i < numsurfaces;i = j)
11209 surface = rsurface.modelsurfaces + surfacelist[i];
11210 texture = surface->texture;
11211 rsurface.texture = R_GetCurrentTexture(texture);
11212 // scan ahead until we find a different texture
11213 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11214 texturenumsurfaces = 0;
11215 texturesurfacelist[texturenumsurfaces++] = surface;
11216 if(FAKELIGHT_ENABLED)
11218 rsurface.lightmaptexture = NULL;
11219 rsurface.deluxemaptexture = NULL;
11220 rsurface.uselightmaptexture = false;
11221 for (;j < endsurface;j++)
11223 surface = rsurface.modelsurfaces + surfacelist[j];
11224 if (texture != surface->texture)
11226 texturesurfacelist[texturenumsurfaces++] = surface;
11231 rsurface.lightmaptexture = surface->lightmaptexture;
11232 rsurface.deluxemaptexture = surface->deluxemaptexture;
11233 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11234 for (;j < endsurface;j++)
11236 surface = rsurface.modelsurfaces + surfacelist[j];
11237 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11239 texturesurfacelist[texturenumsurfaces++] = surface;
11242 // render the range of surfaces
11243 if (ent == r_refdef.scene.worldentity)
11244 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11246 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11248 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11251 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11253 // transparent surfaces get pushed off into the transparent queue
11254 int surfacelistindex;
11255 const msurface_t *surface;
11256 vec3_t tempcenter, center;
11257 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11259 surface = texturesurfacelist[surfacelistindex];
11260 if (r_transparent_sortsurfacesbynearest.integer)
11262 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11263 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11264 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11268 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11269 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11270 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11272 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11273 if (rsurface.entity->transparent_offset) // transparent offset
11275 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11276 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11277 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11279 R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11283 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11285 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11287 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11289 RSurf_SetupDepthAndCulling();
11290 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11291 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11292 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11296 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11300 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11303 if (!rsurface.texture->currentnumlayers)
11305 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11306 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11308 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11310 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11311 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11312 else if (!rsurface.texture->currentnumlayers)
11314 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11316 // in the deferred case, transparent surfaces were queued during prepass
11317 if (!r_shadow_usingdeferredprepass)
11318 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11322 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11323 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11328 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11331 texture_t *texture;
11332 R_FrameData_SetMark();
11333 // break the surface list down into batches by texture and use of lightmapping
11334 for (i = 0;i < numsurfaces;i = j)
11337 // texture is the base texture pointer, rsurface.texture is the
11338 // current frame/skin the texture is directing us to use (for example
11339 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11340 // use skin 1 instead)
11341 texture = surfacelist[i]->texture;
11342 rsurface.texture = R_GetCurrentTexture(texture);
11343 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11345 // if this texture is not the kind we want, skip ahead to the next one
11346 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11350 if(FAKELIGHT_ENABLED || depthonly || prepass)
11352 rsurface.lightmaptexture = NULL;
11353 rsurface.deluxemaptexture = NULL;
11354 rsurface.uselightmaptexture = false;
11355 // simply scan ahead until we find a different texture or lightmap state
11356 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11361 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11362 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11363 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11364 // simply scan ahead until we find a different texture or lightmap state
11365 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11368 // render the range of surfaces
11369 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11371 R_FrameData_ReturnToMark();
11374 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11378 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11381 if (!rsurface.texture->currentnumlayers)
11383 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11384 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11386 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11388 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11389 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11390 else if (!rsurface.texture->currentnumlayers)
11392 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11394 // in the deferred case, transparent surfaces were queued during prepass
11395 if (!r_shadow_usingdeferredprepass)
11396 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11400 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11401 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11406 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11409 texture_t *texture;
11410 R_FrameData_SetMark();
11411 // break the surface list down into batches by texture and use of lightmapping
11412 for (i = 0;i < numsurfaces;i = j)
11415 // texture is the base texture pointer, rsurface.texture is the
11416 // current frame/skin the texture is directing us to use (for example
11417 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11418 // use skin 1 instead)
11419 texture = surfacelist[i]->texture;
11420 rsurface.texture = R_GetCurrentTexture(texture);
11421 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11423 // if this texture is not the kind we want, skip ahead to the next one
11424 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11428 if(FAKELIGHT_ENABLED || depthonly || prepass)
11430 rsurface.lightmaptexture = NULL;
11431 rsurface.deluxemaptexture = NULL;
11432 rsurface.uselightmaptexture = false;
11433 // simply scan ahead until we find a different texture or lightmap state
11434 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11439 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11440 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11441 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11442 // simply scan ahead until we find a different texture or lightmap state
11443 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11446 // render the range of surfaces
11447 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11449 R_FrameData_ReturnToMark();
11452 float locboxvertex3f[6*4*3] =
11454 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11455 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11456 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11457 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11458 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11459 1,0,0, 0,0,0, 0,1,0, 1,1,0
11462 unsigned short locboxelements[6*2*3] =
11467 12,13,14, 12,14,15,
11468 16,17,18, 16,18,19,
11472 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11475 cl_locnode_t *loc = (cl_locnode_t *)ent;
11477 float vertex3f[6*4*3];
11479 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11480 GL_DepthMask(false);
11481 GL_DepthRange(0, 1);
11482 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11483 GL_DepthTest(true);
11484 GL_CullFace(GL_NONE);
11485 R_EntityMatrix(&identitymatrix);
11487 // R_Mesh_ResetTextureState();
11489 i = surfacelist[0];
11490 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11491 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11492 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11493 surfacelist[0] < 0 ? 0.5f : 0.125f);
11495 if (VectorCompare(loc->mins, loc->maxs))
11497 VectorSet(size, 2, 2, 2);
11498 VectorMA(loc->mins, -0.5f, size, mins);
11502 VectorCopy(loc->mins, mins);
11503 VectorSubtract(loc->maxs, loc->mins, size);
11506 for (i = 0;i < 6*4*3;)
11507 for (j = 0;j < 3;j++, i++)
11508 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11510 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11511 R_SetupShader_Generic_NoTexture(false, false);
11512 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11515 void R_DrawLocs(void)
11518 cl_locnode_t *loc, *nearestloc;
11520 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11521 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11523 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11524 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11528 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11530 if (decalsystem->decals)
11531 Mem_Free(decalsystem->decals);
11532 memset(decalsystem, 0, sizeof(*decalsystem));
11535 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)
11538 tridecal_t *decals;
11541 // expand or initialize the system
11542 if (decalsystem->maxdecals <= decalsystem->numdecals)
11544 decalsystem_t old = *decalsystem;
11545 qboolean useshortelements;
11546 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11547 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11548 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)));
11549 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11550 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11551 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11552 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11553 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11554 if (decalsystem->numdecals)
11555 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11557 Mem_Free(old.decals);
11558 for (i = 0;i < decalsystem->maxdecals*3;i++)
11559 decalsystem->element3i[i] = i;
11560 if (useshortelements)
11561 for (i = 0;i < decalsystem->maxdecals*3;i++)
11562 decalsystem->element3s[i] = i;
11565 // grab a decal and search for another free slot for the next one
11566 decals = decalsystem->decals;
11567 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11568 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11570 decalsystem->freedecal = i;
11571 if (decalsystem->numdecals <= i)
11572 decalsystem->numdecals = i + 1;
11574 // initialize the decal
11576 decal->triangleindex = triangleindex;
11577 decal->surfaceindex = surfaceindex;
11578 decal->decalsequence = decalsequence;
11579 decal->color4f[0][0] = c0[0];
11580 decal->color4f[0][1] = c0[1];
11581 decal->color4f[0][2] = c0[2];
11582 decal->color4f[0][3] = 1;
11583 decal->color4f[1][0] = c1[0];
11584 decal->color4f[1][1] = c1[1];
11585 decal->color4f[1][2] = c1[2];
11586 decal->color4f[1][3] = 1;
11587 decal->color4f[2][0] = c2[0];
11588 decal->color4f[2][1] = c2[1];
11589 decal->color4f[2][2] = c2[2];
11590 decal->color4f[2][3] = 1;
11591 decal->vertex3f[0][0] = v0[0];
11592 decal->vertex3f[0][1] = v0[1];
11593 decal->vertex3f[0][2] = v0[2];
11594 decal->vertex3f[1][0] = v1[0];
11595 decal->vertex3f[1][1] = v1[1];
11596 decal->vertex3f[1][2] = v1[2];
11597 decal->vertex3f[2][0] = v2[0];
11598 decal->vertex3f[2][1] = v2[1];
11599 decal->vertex3f[2][2] = v2[2];
11600 decal->texcoord2f[0][0] = t0[0];
11601 decal->texcoord2f[0][1] = t0[1];
11602 decal->texcoord2f[1][0] = t1[0];
11603 decal->texcoord2f[1][1] = t1[1];
11604 decal->texcoord2f[2][0] = t2[0];
11605 decal->texcoord2f[2][1] = t2[1];
11606 TriangleNormal(v0, v1, v2, decal->plane);
11607 VectorNormalize(decal->plane);
11608 decal->plane[3] = DotProduct(v0, decal->plane);
11611 extern cvar_t cl_decals_bias;
11612 extern cvar_t cl_decals_models;
11613 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11614 // baseparms, parms, temps
11615 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)
11620 const float *vertex3f;
11621 const float *normal3f;
11623 float points[2][9][3];
11630 e = rsurface.modelelement3i + 3*triangleindex;
11632 vertex3f = rsurface.modelvertex3f;
11633 normal3f = rsurface.modelnormal3f;
11637 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11639 index = 3*e[cornerindex];
11640 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11645 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11647 index = 3*e[cornerindex];
11648 VectorCopy(vertex3f + index, v[cornerindex]);
11653 //TriangleNormal(v[0], v[1], v[2], normal);
11654 //if (DotProduct(normal, localnormal) < 0.0f)
11656 // clip by each of the box planes formed from the projection matrix
11657 // if anything survives, we emit the decal
11658 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]);
11661 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]);
11664 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]);
11667 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]);
11670 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]);
11673 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]);
11676 // some part of the triangle survived, so we have to accept it...
11679 // dynamic always uses the original triangle
11681 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11683 index = 3*e[cornerindex];
11684 VectorCopy(vertex3f + index, v[cornerindex]);
11687 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11689 // convert vertex positions to texcoords
11690 Matrix4x4_Transform(projection, v[cornerindex], temp);
11691 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11692 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11693 // calculate distance fade from the projection origin
11694 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11695 f = bound(0.0f, f, 1.0f);
11696 c[cornerindex][0] = r * f;
11697 c[cornerindex][1] = g * f;
11698 c[cornerindex][2] = b * f;
11699 c[cornerindex][3] = 1.0f;
11700 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11703 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);
11705 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11706 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);
11708 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)
11710 matrix4x4_t projection;
11711 decalsystem_t *decalsystem;
11714 const msurface_t *surface;
11715 const msurface_t *surfaces;
11716 const int *surfacelist;
11717 const texture_t *texture;
11719 int numsurfacelist;
11720 int surfacelistindex;
11723 float localorigin[3];
11724 float localnormal[3];
11725 float localmins[3];
11726 float localmaxs[3];
11729 float planes[6][4];
11732 int bih_triangles_count;
11733 int bih_triangles[256];
11734 int bih_surfaces[256];
11736 decalsystem = &ent->decalsystem;
11737 model = ent->model;
11738 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11740 R_DecalSystem_Reset(&ent->decalsystem);
11744 if (!model->brush.data_leafs && !cl_decals_models.integer)
11746 if (decalsystem->model)
11747 R_DecalSystem_Reset(decalsystem);
11751 if (decalsystem->model != model)
11752 R_DecalSystem_Reset(decalsystem);
11753 decalsystem->model = model;
11755 RSurf_ActiveModelEntity(ent, true, false, false);
11757 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11758 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11759 VectorNormalize(localnormal);
11760 localsize = worldsize*rsurface.inversematrixscale;
11761 localmins[0] = localorigin[0] - localsize;
11762 localmins[1] = localorigin[1] - localsize;
11763 localmins[2] = localorigin[2] - localsize;
11764 localmaxs[0] = localorigin[0] + localsize;
11765 localmaxs[1] = localorigin[1] + localsize;
11766 localmaxs[2] = localorigin[2] + localsize;
11768 //VectorCopy(localnormal, planes[4]);
11769 //VectorVectors(planes[4], planes[2], planes[0]);
11770 AnglesFromVectors(angles, localnormal, NULL, false);
11771 AngleVectors(angles, planes[0], planes[2], planes[4]);
11772 VectorNegate(planes[0], planes[1]);
11773 VectorNegate(planes[2], planes[3]);
11774 VectorNegate(planes[4], planes[5]);
11775 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11776 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11777 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11778 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11779 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11780 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11785 matrix4x4_t forwardprojection;
11786 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11787 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11792 float projectionvector[4][3];
11793 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11794 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11795 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11796 projectionvector[0][0] = planes[0][0] * ilocalsize;
11797 projectionvector[0][1] = planes[1][0] * ilocalsize;
11798 projectionvector[0][2] = planes[2][0] * ilocalsize;
11799 projectionvector[1][0] = planes[0][1] * ilocalsize;
11800 projectionvector[1][1] = planes[1][1] * ilocalsize;
11801 projectionvector[1][2] = planes[2][1] * ilocalsize;
11802 projectionvector[2][0] = planes[0][2] * ilocalsize;
11803 projectionvector[2][1] = planes[1][2] * ilocalsize;
11804 projectionvector[2][2] = planes[2][2] * ilocalsize;
11805 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11806 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11807 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11808 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11812 dynamic = model->surfmesh.isanimated;
11813 numsurfacelist = model->nummodelsurfaces;
11814 surfacelist = model->sortedmodelsurfaces;
11815 surfaces = model->data_surfaces;
11818 bih_triangles_count = -1;
11821 if(model->render_bih.numleafs)
11822 bih = &model->render_bih;
11823 else if(model->collision_bih.numleafs)
11824 bih = &model->collision_bih;
11827 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11828 if(bih_triangles_count == 0)
11830 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11832 if(bih_triangles_count > 0)
11834 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11836 surfaceindex = bih_surfaces[triangleindex];
11837 surface = surfaces + surfaceindex;
11838 texture = surface->texture;
11839 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11841 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11843 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11848 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11850 surfaceindex = surfacelist[surfacelistindex];
11851 surface = surfaces + surfaceindex;
11852 // check cull box first because it rejects more than any other check
11853 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11855 // skip transparent surfaces
11856 texture = surface->texture;
11857 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11859 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11861 numtriangles = surface->num_triangles;
11862 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11863 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11868 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11869 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)
11871 int renderentityindex;
11872 float worldmins[3];
11873 float worldmaxs[3];
11874 entity_render_t *ent;
11876 if (!cl_decals_newsystem.integer)
11879 worldmins[0] = worldorigin[0] - worldsize;
11880 worldmins[1] = worldorigin[1] - worldsize;
11881 worldmins[2] = worldorigin[2] - worldsize;
11882 worldmaxs[0] = worldorigin[0] + worldsize;
11883 worldmaxs[1] = worldorigin[1] + worldsize;
11884 worldmaxs[2] = worldorigin[2] + worldsize;
11886 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11888 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11890 ent = r_refdef.scene.entities[renderentityindex];
11891 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11894 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11898 typedef struct r_decalsystem_splatqueue_s
11900 vec3_t worldorigin;
11901 vec3_t worldnormal;
11907 r_decalsystem_splatqueue_t;
11909 int r_decalsystem_numqueued = 0;
11910 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11912 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)
11914 r_decalsystem_splatqueue_t *queue;
11916 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11919 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11920 VectorCopy(worldorigin, queue->worldorigin);
11921 VectorCopy(worldnormal, queue->worldnormal);
11922 Vector4Set(queue->color, r, g, b, a);
11923 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11924 queue->worldsize = worldsize;
11925 queue->decalsequence = cl.decalsequence++;
11928 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11931 r_decalsystem_splatqueue_t *queue;
11933 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11934 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);
11935 r_decalsystem_numqueued = 0;
11938 extern cvar_t cl_decals_max;
11939 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11942 decalsystem_t *decalsystem = &ent->decalsystem;
11949 if (!decalsystem->numdecals)
11952 if (r_showsurfaces.integer)
11955 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11957 R_DecalSystem_Reset(decalsystem);
11961 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11962 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11964 if (decalsystem->lastupdatetime)
11965 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11968 decalsystem->lastupdatetime = r_refdef.scene.time;
11969 numdecals = decalsystem->numdecals;
11971 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11973 if (decal->color4f[0][3])
11975 decal->lived += frametime;
11976 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11978 memset(decal, 0, sizeof(*decal));
11979 if (decalsystem->freedecal > i)
11980 decalsystem->freedecal = i;
11984 decal = decalsystem->decals;
11985 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11988 // collapse the array by shuffling the tail decals into the gaps
11991 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11992 decalsystem->freedecal++;
11993 if (decalsystem->freedecal == numdecals)
11995 decal[decalsystem->freedecal] = decal[--numdecals];
11998 decalsystem->numdecals = numdecals;
12000 if (numdecals <= 0)
12002 // if there are no decals left, reset decalsystem
12003 R_DecalSystem_Reset(decalsystem);
12007 extern skinframe_t *decalskinframe;
12008 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12011 decalsystem_t *decalsystem = &ent->decalsystem;
12020 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12023 numdecals = decalsystem->numdecals;
12027 if (r_showsurfaces.integer)
12030 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12032 R_DecalSystem_Reset(decalsystem);
12036 // if the model is static it doesn't matter what value we give for
12037 // wantnormals and wanttangents, so this logic uses only rules applicable
12038 // to a model, knowing that they are meaningless otherwise
12039 if (ent == r_refdef.scene.worldentity)
12040 RSurf_ActiveWorldEntity();
12042 RSurf_ActiveModelEntity(ent, false, false, false);
12044 decalsystem->lastupdatetime = r_refdef.scene.time;
12046 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12048 // update vertex positions for animated models
12049 v3f = decalsystem->vertex3f;
12050 c4f = decalsystem->color4f;
12051 t2f = decalsystem->texcoord2f;
12052 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12054 if (!decal->color4f[0][3])
12057 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12061 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12064 // update color values for fading decals
12065 if (decal->lived >= cl_decals_time.value)
12066 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12070 c4f[ 0] = decal->color4f[0][0] * alpha;
12071 c4f[ 1] = decal->color4f[0][1] * alpha;
12072 c4f[ 2] = decal->color4f[0][2] * alpha;
12074 c4f[ 4] = decal->color4f[1][0] * alpha;
12075 c4f[ 5] = decal->color4f[1][1] * alpha;
12076 c4f[ 6] = decal->color4f[1][2] * alpha;
12078 c4f[ 8] = decal->color4f[2][0] * alpha;
12079 c4f[ 9] = decal->color4f[2][1] * alpha;
12080 c4f[10] = decal->color4f[2][2] * alpha;
12083 t2f[0] = decal->texcoord2f[0][0];
12084 t2f[1] = decal->texcoord2f[0][1];
12085 t2f[2] = decal->texcoord2f[1][0];
12086 t2f[3] = decal->texcoord2f[1][1];
12087 t2f[4] = decal->texcoord2f[2][0];
12088 t2f[5] = decal->texcoord2f[2][1];
12090 // update vertex positions for animated models
12091 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12093 e = rsurface.modelelement3i + 3*decal->triangleindex;
12094 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12095 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12096 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12100 VectorCopy(decal->vertex3f[0], v3f);
12101 VectorCopy(decal->vertex3f[1], v3f + 3);
12102 VectorCopy(decal->vertex3f[2], v3f + 6);
12105 if (r_refdef.fogenabled)
12107 alpha = RSurf_FogVertex(v3f);
12108 VectorScale(c4f, alpha, c4f);
12109 alpha = RSurf_FogVertex(v3f + 3);
12110 VectorScale(c4f + 4, alpha, c4f + 4);
12111 alpha = RSurf_FogVertex(v3f + 6);
12112 VectorScale(c4f + 8, alpha, c4f + 8);
12123 r_refdef.stats[r_stat_drawndecals] += numtris;
12125 // now render the decals all at once
12126 // (this assumes they all use one particle font texture!)
12127 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);
12128 // R_Mesh_ResetTextureState();
12129 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12130 GL_DepthMask(false);
12131 GL_DepthRange(0, 1);
12132 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12133 GL_DepthTest(true);
12134 GL_CullFace(GL_NONE);
12135 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12136 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12137 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12141 static void R_DrawModelDecals(void)
12145 // fade faster when there are too many decals
12146 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12147 for (i = 0;i < r_refdef.scene.numentities;i++)
12148 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12150 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12151 for (i = 0;i < r_refdef.scene.numentities;i++)
12152 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12153 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12155 R_DecalSystem_ApplySplatEntitiesQueue();
12157 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12158 for (i = 0;i < r_refdef.scene.numentities;i++)
12159 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12161 r_refdef.stats[r_stat_totaldecals] += numdecals;
12163 if (r_showsurfaces.integer)
12166 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12168 for (i = 0;i < r_refdef.scene.numentities;i++)
12170 if (!r_refdef.viewcache.entityvisible[i])
12172 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12173 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12177 extern cvar_t mod_collision_bih;
12178 static void R_DrawDebugModel(void)
12180 entity_render_t *ent = rsurface.entity;
12181 int i, j, k, l, flagsmask;
12182 const msurface_t *surface;
12183 dp_model_t *model = ent->model;
12186 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12189 if (r_showoverdraw.value > 0)
12191 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12192 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12193 R_SetupShader_Generic_NoTexture(false, false);
12194 GL_DepthTest(false);
12195 GL_DepthMask(false);
12196 GL_DepthRange(0, 1);
12197 GL_BlendFunc(GL_ONE, GL_ONE);
12198 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12200 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12202 rsurface.texture = R_GetCurrentTexture(surface->texture);
12203 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12205 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12206 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12207 if (!rsurface.texture->currentlayers->depthmask)
12208 GL_Color(c, 0, 0, 1.0f);
12209 else if (ent == r_refdef.scene.worldentity)
12210 GL_Color(c, c, c, 1.0f);
12212 GL_Color(0, c, 0, 1.0f);
12213 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12217 rsurface.texture = NULL;
12220 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12222 // R_Mesh_ResetTextureState();
12223 R_SetupShader_Generic_NoTexture(false, false);
12224 GL_DepthRange(0, 1);
12225 GL_DepthTest(!r_showdisabledepthtest.integer);
12226 GL_DepthMask(false);
12227 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12229 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12233 qboolean cullbox = false;
12234 const q3mbrush_t *brush;
12235 const bih_t *bih = &model->collision_bih;
12236 const bih_leaf_t *bihleaf;
12237 float vertex3f[3][3];
12238 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12239 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12241 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12243 switch (bihleaf->type)
12246 brush = model->brush.data_brushes + bihleaf->itemindex;
12247 if (brush->colbrushf && brush->colbrushf->numtriangles)
12249 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);
12250 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12251 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12254 case BIH_COLLISIONTRIANGLE:
12255 triangleindex = bihleaf->itemindex;
12256 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12257 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12258 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12259 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);
12260 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12261 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12263 case BIH_RENDERTRIANGLE:
12264 triangleindex = bihleaf->itemindex;
12265 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12266 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12267 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12268 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);
12269 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12270 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12276 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12279 if (r_showtris.integer && qglPolygonMode)
12281 if (r_showdisabledepthtest.integer)
12283 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12284 GL_DepthMask(false);
12288 GL_BlendFunc(GL_ONE, GL_ZERO);
12289 GL_DepthMask(true);
12291 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12292 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12294 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12296 rsurface.texture = R_GetCurrentTexture(surface->texture);
12297 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12299 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12300 if (!rsurface.texture->currentlayers->depthmask)
12301 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12302 else if (ent == r_refdef.scene.worldentity)
12303 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12305 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12306 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12310 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12311 rsurface.texture = NULL;
12314 if (r_shownormals.value != 0 && qglBegin)
12316 if (r_showdisabledepthtest.integer)
12318 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12319 GL_DepthMask(false);
12323 GL_BlendFunc(GL_ONE, GL_ZERO);
12324 GL_DepthMask(true);
12326 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12328 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12330 rsurface.texture = R_GetCurrentTexture(surface->texture);
12331 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12333 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12334 qglBegin(GL_LINES);
12335 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12337 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12339 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12340 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12341 qglVertex3f(v[0], v[1], v[2]);
12342 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12343 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12344 qglVertex3f(v[0], v[1], v[2]);
12347 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12349 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12351 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12352 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12353 qglVertex3f(v[0], v[1], v[2]);
12354 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12355 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12356 qglVertex3f(v[0], v[1], v[2]);
12359 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12361 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12363 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12364 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12365 qglVertex3f(v[0], v[1], v[2]);
12366 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12367 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12368 qglVertex3f(v[0], v[1], v[2]);
12371 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12373 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12375 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12376 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12377 qglVertex3f(v[0], v[1], v[2]);
12378 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12379 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12380 qglVertex3f(v[0], v[1], v[2]);
12387 rsurface.texture = NULL;
12392 int r_maxsurfacelist = 0;
12393 const msurface_t **r_surfacelist = NULL;
12394 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12396 int i, j, endj, flagsmask;
12397 dp_model_t *model = r_refdef.scene.worldmodel;
12398 msurface_t *surfaces;
12399 unsigned char *update;
12400 int numsurfacelist = 0;
12404 if (r_maxsurfacelist < model->num_surfaces)
12406 r_maxsurfacelist = model->num_surfaces;
12408 Mem_Free((msurface_t**)r_surfacelist);
12409 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12412 RSurf_ActiveWorldEntity();
12414 surfaces = model->data_surfaces;
12415 update = model->brushq1.lightmapupdateflags;
12417 // update light styles on this submodel
12418 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12420 model_brush_lightstyleinfo_t *style;
12421 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12423 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12425 int *list = style->surfacelist;
12426 style->value = r_refdef.scene.lightstylevalue[style->style];
12427 for (j = 0;j < style->numsurfaces;j++)
12428 update[list[j]] = true;
12433 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12437 R_DrawDebugModel();
12438 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12442 rsurface.lightmaptexture = NULL;
12443 rsurface.deluxemaptexture = NULL;
12444 rsurface.uselightmaptexture = false;
12445 rsurface.texture = NULL;
12446 rsurface.rtlight = NULL;
12447 numsurfacelist = 0;
12448 // add visible surfaces to draw list
12449 for (i = 0;i < model->nummodelsurfaces;i++)
12451 j = model->sortedmodelsurfaces[i];
12452 if (r_refdef.viewcache.world_surfacevisible[j])
12453 r_surfacelist[numsurfacelist++] = surfaces + j;
12455 // update lightmaps if needed
12456 if (model->brushq1.firstrender)
12458 model->brushq1.firstrender = false;
12459 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12461 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12465 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12466 if (r_refdef.viewcache.world_surfacevisible[j])
12468 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12470 // don't do anything if there were no surfaces
12471 if (!numsurfacelist)
12473 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12476 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12478 // add to stats if desired
12479 if (r_speeds.integer && !skysurfaces && !depthonly)
12481 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12482 for (j = 0;j < numsurfacelist;j++)
12483 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12486 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12489 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12491 int i, j, endj, flagsmask;
12492 dp_model_t *model = ent->model;
12493 msurface_t *surfaces;
12494 unsigned char *update;
12495 int numsurfacelist = 0;
12499 if (r_maxsurfacelist < model->num_surfaces)
12501 r_maxsurfacelist = model->num_surfaces;
12503 Mem_Free((msurface_t **)r_surfacelist);
12504 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12507 // if the model is static it doesn't matter what value we give for
12508 // wantnormals and wanttangents, so this logic uses only rules applicable
12509 // to a model, knowing that they are meaningless otherwise
12510 if (ent == r_refdef.scene.worldentity)
12511 RSurf_ActiveWorldEntity();
12512 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12513 RSurf_ActiveModelEntity(ent, false, false, false);
12515 RSurf_ActiveModelEntity(ent, true, true, true);
12516 else if (depthonly)
12518 switch (vid.renderpath)
12520 case RENDERPATH_GL20:
12521 case RENDERPATH_D3D9:
12522 case RENDERPATH_D3D10:
12523 case RENDERPATH_D3D11:
12524 case RENDERPATH_SOFT:
12525 case RENDERPATH_GLES2:
12526 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12528 case RENDERPATH_GL11:
12529 case RENDERPATH_GL13:
12530 case RENDERPATH_GLES1:
12531 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12537 switch (vid.renderpath)
12539 case RENDERPATH_GL20:
12540 case RENDERPATH_D3D9:
12541 case RENDERPATH_D3D10:
12542 case RENDERPATH_D3D11:
12543 case RENDERPATH_SOFT:
12544 case RENDERPATH_GLES2:
12545 RSurf_ActiveModelEntity(ent, true, true, false);
12547 case RENDERPATH_GL11:
12548 case RENDERPATH_GL13:
12549 case RENDERPATH_GLES1:
12550 RSurf_ActiveModelEntity(ent, true, false, false);
12555 surfaces = model->data_surfaces;
12556 update = model->brushq1.lightmapupdateflags;
12558 // update light styles
12559 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12561 model_brush_lightstyleinfo_t *style;
12562 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12564 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12566 int *list = style->surfacelist;
12567 style->value = r_refdef.scene.lightstylevalue[style->style];
12568 for (j = 0;j < style->numsurfaces;j++)
12569 update[list[j]] = true;
12574 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12578 R_DrawDebugModel();
12579 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12583 rsurface.lightmaptexture = NULL;
12584 rsurface.deluxemaptexture = NULL;
12585 rsurface.uselightmaptexture = false;
12586 rsurface.texture = NULL;
12587 rsurface.rtlight = NULL;
12588 numsurfacelist = 0;
12589 // add visible surfaces to draw list
12590 for (i = 0;i < model->nummodelsurfaces;i++)
12591 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12592 // don't do anything if there were no surfaces
12593 if (!numsurfacelist)
12595 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12598 // update lightmaps if needed
12602 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12607 R_BuildLightMap(ent, surfaces + j);
12612 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12614 // add to stats if desired
12615 if (r_speeds.integer && !skysurfaces && !depthonly)
12617 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12618 for (j = 0;j < numsurfacelist;j++)
12619 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12622 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12625 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12627 static texture_t texture;
12628 static msurface_t surface;
12629 const msurface_t *surfacelist = &surface;
12631 // fake enough texture and surface state to render this geometry
12633 texture.update_lastrenderframe = -1; // regenerate this texture
12634 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12635 texture.currentskinframe = skinframe;
12636 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12637 texture.offsetmapping = OFFSETMAPPING_OFF;
12638 texture.offsetscale = 1;
12639 texture.specularscalemod = 1;
12640 texture.specularpowermod = 1;
12641 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12642 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12643 // JUST GREP FOR "specularscalemod = 1".
12645 surface.texture = &texture;
12646 surface.num_triangles = numtriangles;
12647 surface.num_firsttriangle = firsttriangle;
12648 surface.num_vertices = numvertices;
12649 surface.num_firstvertex = firstvertex;
12652 rsurface.texture = R_GetCurrentTexture(surface.texture);
12653 rsurface.lightmaptexture = NULL;
12654 rsurface.deluxemaptexture = NULL;
12655 rsurface.uselightmaptexture = false;
12656 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12659 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)
12661 static msurface_t surface;
12662 const msurface_t *surfacelist = &surface;
12664 // fake enough texture and surface state to render this geometry
12665 surface.texture = texture;
12666 surface.num_triangles = numtriangles;
12667 surface.num_firsttriangle = firsttriangle;
12668 surface.num_vertices = numvertices;
12669 surface.num_firstvertex = firstvertex;
12672 rsurface.texture = R_GetCurrentTexture(surface.texture);
12673 rsurface.lightmaptexture = NULL;
12674 rsurface.deluxemaptexture = NULL;
12675 rsurface.uselightmaptexture = false;
12676 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);