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_bufferdatasize[R_BUFFERDATA_COUNT] =
243 {CVAR_SAVE, "r_bufferdatasize_vertex", "4", "vertex buffer size for one frame"},
244 {CVAR_SAVE, "r_bufferdatasize_index16", "1", "index buffer size for one frame (16bit indices)"},
245 {CVAR_SAVE, "r_bufferdatasize_index32", "1", "index buffer size for one frame (32bit indices)"},
246 {CVAR_SAVE, "r_bufferdatasize_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 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1315 // clear the uniform block bindings
1316 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1317 // bind the uniform blocks in use
1319 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1320 // we're done compiling and setting up the shader, at least until it is used
1322 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1325 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1329 Mem_Free(sourcestring);
1332 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1334 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1335 if (r_glsl_permutation != perm)
1337 r_glsl_permutation = perm;
1338 if (!r_glsl_permutation->program)
1340 if (!r_glsl_permutation->compiled)
1341 R_GLSL_CompilePermutation(perm, mode, permutation);
1342 if (!r_glsl_permutation->program)
1344 // remove features until we find a valid permutation
1346 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1348 // reduce i more quickly whenever it would not remove any bits
1349 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1350 if (!(permutation & j))
1353 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1354 if (!r_glsl_permutation->compiled)
1355 R_GLSL_CompilePermutation(perm, mode, permutation);
1356 if (r_glsl_permutation->program)
1359 if (i >= SHADERPERMUTATION_COUNT)
1361 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1362 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1363 qglUseProgram(0);CHECKGLERROR
1364 return; // no bit left to clear, entire mode is broken
1369 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1371 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1372 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1373 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1380 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1381 extern D3DCAPS9 vid_d3d9caps;
1384 struct r_hlsl_permutation_s;
1385 typedef struct r_hlsl_permutation_s
1387 /// hash lookup data
1388 struct r_hlsl_permutation_s *hashnext;
1390 unsigned int permutation;
1392 /// indicates if we have tried compiling this permutation already
1394 /// NULL if compilation failed
1395 IDirect3DVertexShader9 *vertexshader;
1396 IDirect3DPixelShader9 *pixelshader;
1398 r_hlsl_permutation_t;
1400 typedef enum D3DVSREGISTER_e
1402 D3DVSREGISTER_TexMatrix = 0, // float4x4
1403 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1404 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1405 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1406 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1407 D3DVSREGISTER_ModelToLight = 20, // float4x4
1408 D3DVSREGISTER_EyePosition = 24,
1409 D3DVSREGISTER_FogPlane = 25,
1410 D3DVSREGISTER_LightDir = 26,
1411 D3DVSREGISTER_LightPosition = 27,
1415 typedef enum D3DPSREGISTER_e
1417 D3DPSREGISTER_Alpha = 0,
1418 D3DPSREGISTER_BloomBlur_Parameters = 1,
1419 D3DPSREGISTER_ClientTime = 2,
1420 D3DPSREGISTER_Color_Ambient = 3,
1421 D3DPSREGISTER_Color_Diffuse = 4,
1422 D3DPSREGISTER_Color_Specular = 5,
1423 D3DPSREGISTER_Color_Glow = 6,
1424 D3DPSREGISTER_Color_Pants = 7,
1425 D3DPSREGISTER_Color_Shirt = 8,
1426 D3DPSREGISTER_DeferredColor_Ambient = 9,
1427 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1428 D3DPSREGISTER_DeferredColor_Specular = 11,
1429 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1430 D3DPSREGISTER_DeferredMod_Specular = 13,
1431 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1432 D3DPSREGISTER_EyePosition = 15, // unused
1433 D3DPSREGISTER_FogColor = 16,
1434 D3DPSREGISTER_FogHeightFade = 17,
1435 D3DPSREGISTER_FogPlane = 18,
1436 D3DPSREGISTER_FogPlaneViewDist = 19,
1437 D3DPSREGISTER_FogRangeRecip = 20,
1438 D3DPSREGISTER_LightColor = 21,
1439 D3DPSREGISTER_LightDir = 22, // unused
1440 D3DPSREGISTER_LightPosition = 23,
1441 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1442 D3DPSREGISTER_PixelSize = 25,
1443 D3DPSREGISTER_ReflectColor = 26,
1444 D3DPSREGISTER_ReflectFactor = 27,
1445 D3DPSREGISTER_ReflectOffset = 28,
1446 D3DPSREGISTER_RefractColor = 29,
1447 D3DPSREGISTER_Saturation = 30,
1448 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1449 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1450 D3DPSREGISTER_ScreenToDepth = 33,
1451 D3DPSREGISTER_ShadowMap_Parameters = 34,
1452 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1453 D3DPSREGISTER_SpecularPower = 36,
1454 D3DPSREGISTER_UserVec1 = 37,
1455 D3DPSREGISTER_UserVec2 = 38,
1456 D3DPSREGISTER_UserVec3 = 39,
1457 D3DPSREGISTER_UserVec4 = 40,
1458 D3DPSREGISTER_ViewTintColor = 41,
1459 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1460 D3DPSREGISTER_BloomColorSubtract = 43,
1461 D3DPSREGISTER_ViewToLight = 44, // float4x4
1462 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1463 D3DPSREGISTER_NormalmapScrollBlend = 52,
1464 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1465 D3DPSREGISTER_OffsetMapping_Bias = 54,
1470 /// information about each possible shader permutation
1471 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1472 /// currently selected permutation
1473 r_hlsl_permutation_t *r_hlsl_permutation;
1474 /// storage for permutations linked in the hash table
1475 memexpandablearray_t r_hlsl_permutationarray;
1477 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1479 //unsigned int hashdepth = 0;
1480 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1481 r_hlsl_permutation_t *p;
1482 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1484 if (p->mode == mode && p->permutation == permutation)
1486 //if (hashdepth > 10)
1487 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1492 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1494 p->permutation = permutation;
1495 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1496 r_hlsl_permutationhash[mode][hashindex] = p;
1497 //if (hashdepth > 10)
1498 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1503 //#include <d3dx9shader.h>
1504 //#include <d3dx9mesh.h>
1506 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1508 DWORD *vsbin = NULL;
1509 DWORD *psbin = NULL;
1510 fs_offset_t vsbinsize;
1511 fs_offset_t psbinsize;
1512 // IDirect3DVertexShader9 *vs = NULL;
1513 // IDirect3DPixelShader9 *ps = NULL;
1514 ID3DXBuffer *vslog = NULL;
1515 ID3DXBuffer *vsbuffer = NULL;
1516 ID3DXConstantTable *vsconstanttable = NULL;
1517 ID3DXBuffer *pslog = NULL;
1518 ID3DXBuffer *psbuffer = NULL;
1519 ID3DXConstantTable *psconstanttable = NULL;
1522 char temp[MAX_INPUTLINE];
1523 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1525 qboolean debugshader = gl_paranoid.integer != 0;
1526 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1527 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1530 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1531 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1533 if ((!vsbin && vertstring) || (!psbin && fragstring))
1535 const char* dllnames_d3dx9 [] =
1559 dllhandle_t d3dx9_dll = NULL;
1560 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1561 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1562 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1563 dllfunction_t d3dx9_dllfuncs[] =
1565 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1566 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1567 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1570 // 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...
1571 #ifndef ID3DXBuffer_GetBufferPointer
1572 #if !defined(__cplusplus) || defined(CINTERFACE)
1573 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1574 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1575 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1577 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1578 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1579 #define ID3DXBuffer_Release(p) (p)->Release()
1582 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1584 DWORD shaderflags = 0;
1586 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1587 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1588 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1589 if (vertstring && vertstring[0])
1593 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1594 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1597 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1600 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1601 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1602 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1603 ID3DXBuffer_Release(vsbuffer);
1607 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1608 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1609 ID3DXBuffer_Release(vslog);
1612 if (fragstring && fragstring[0])
1616 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1617 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1620 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1623 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1624 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1625 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1626 ID3DXBuffer_Release(psbuffer);
1630 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1631 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1632 ID3DXBuffer_Release(pslog);
1635 Sys_UnloadLibrary(&d3dx9_dll);
1638 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1642 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1643 if (FAILED(vsresult))
1644 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1645 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1646 if (FAILED(psresult))
1647 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1649 // free the shader data
1650 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1651 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1654 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1657 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1658 int vertstring_length = 0;
1659 int geomstring_length = 0;
1660 int fragstring_length = 0;
1663 char *vertstring, *geomstring, *fragstring;
1664 char permutationname[256];
1665 char cachename[256];
1666 int vertstrings_count = 0;
1667 int geomstrings_count = 0;
1668 int fragstrings_count = 0;
1669 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1670 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1671 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1676 p->vertexshader = NULL;
1677 p->pixelshader = NULL;
1679 permutationname[0] = 0;
1681 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1683 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1684 strlcat(cachename, "hlsl/", sizeof(cachename));
1686 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1687 vertstrings_count = 0;
1688 geomstrings_count = 0;
1689 fragstrings_count = 0;
1690 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1691 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1692 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1694 // the first pretext is which type of shader to compile as
1695 // (later these will all be bound together as a program object)
1696 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1697 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1698 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1700 // the second pretext is the mode (for example a light source)
1701 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1702 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1703 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1704 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1705 strlcat(cachename, modeinfo->name, sizeof(cachename));
1707 // now add all the permutation pretexts
1708 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1710 if (permutation & (1<<i))
1712 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1713 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1714 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1715 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1716 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1720 // keep line numbers correct
1721 vertstrings_list[vertstrings_count++] = "\n";
1722 geomstrings_list[geomstrings_count++] = "\n";
1723 fragstrings_list[fragstrings_count++] = "\n";
1728 R_CompileShader_AddStaticParms(mode, permutation);
1729 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1730 vertstrings_count += shaderstaticparms_count;
1731 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1732 geomstrings_count += shaderstaticparms_count;
1733 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1734 fragstrings_count += shaderstaticparms_count;
1736 // replace spaces in the cachename with _ characters
1737 for (i = 0;cachename[i];i++)
1738 if (cachename[i] == ' ')
1741 // now append the shader text itself
1742 vertstrings_list[vertstrings_count++] = sourcestring;
1743 geomstrings_list[geomstrings_count++] = sourcestring;
1744 fragstrings_list[fragstrings_count++] = sourcestring;
1746 vertstring_length = 0;
1747 for (i = 0;i < vertstrings_count;i++)
1748 vertstring_length += strlen(vertstrings_list[i]);
1749 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1750 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1751 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1753 geomstring_length = 0;
1754 for (i = 0;i < geomstrings_count;i++)
1755 geomstring_length += strlen(geomstrings_list[i]);
1756 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1757 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1758 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1760 fragstring_length = 0;
1761 for (i = 0;i < fragstrings_count;i++)
1762 fragstring_length += strlen(fragstrings_list[i]);
1763 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1764 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1765 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1767 // try to load the cached shader, or generate one
1768 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1770 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1771 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1773 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1777 Mem_Free(vertstring);
1779 Mem_Free(geomstring);
1781 Mem_Free(fragstring);
1783 Mem_Free(sourcestring);
1786 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1787 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1788 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);}
1789 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);}
1790 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);}
1791 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);}
1793 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1794 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1795 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);}
1796 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);}
1797 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);}
1798 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);}
1800 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1802 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1803 if (r_hlsl_permutation != perm)
1805 r_hlsl_permutation = perm;
1806 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1808 if (!r_hlsl_permutation->compiled)
1809 R_HLSL_CompilePermutation(perm, mode, permutation);
1810 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1812 // remove features until we find a valid permutation
1814 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1816 // reduce i more quickly whenever it would not remove any bits
1817 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1818 if (!(permutation & j))
1821 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1822 if (!r_hlsl_permutation->compiled)
1823 R_HLSL_CompilePermutation(perm, mode, permutation);
1824 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1827 if (i >= SHADERPERMUTATION_COUNT)
1829 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1830 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1831 return; // no bit left to clear, entire mode is broken
1835 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1836 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1838 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1839 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1840 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1844 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1846 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1847 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1848 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1849 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1852 void R_GLSL_Restart_f(void)
1854 unsigned int i, limit;
1855 if (glslshaderstring)
1856 Mem_Free(glslshaderstring);
1857 glslshaderstring = NULL;
1858 if (hlslshaderstring)
1859 Mem_Free(hlslshaderstring);
1860 hlslshaderstring = NULL;
1861 switch(vid.renderpath)
1863 case RENDERPATH_D3D9:
1866 r_hlsl_permutation_t *p;
1867 r_hlsl_permutation = NULL;
1868 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1869 for (i = 0;i < limit;i++)
1871 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1873 if (p->vertexshader)
1874 IDirect3DVertexShader9_Release(p->vertexshader);
1876 IDirect3DPixelShader9_Release(p->pixelshader);
1877 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1880 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1884 case RENDERPATH_D3D10:
1885 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1887 case RENDERPATH_D3D11:
1888 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1890 case RENDERPATH_GL20:
1891 case RENDERPATH_GLES2:
1893 r_glsl_permutation_t *p;
1894 r_glsl_permutation = NULL;
1895 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1896 for (i = 0;i < limit;i++)
1898 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1900 GL_Backend_FreeProgram(p->program);
1901 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1904 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1907 case RENDERPATH_GL11:
1908 case RENDERPATH_GL13:
1909 case RENDERPATH_GLES1:
1911 case RENDERPATH_SOFT:
1916 static void R_GLSL_DumpShader_f(void)
1918 int i, language, mode, dupe;
1920 shadermodeinfo_t *modeinfo;
1923 for (language = 0;language < 2;language++)
1925 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1926 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1928 // don't dump the same file multiple times (most or all shaders come from the same file)
1929 for (dupe = mode - 1;dupe >= 0;dupe--)
1930 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1934 text = R_GetShaderText(modeinfo[mode].filename, false, true);
1937 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1940 FS_Print(file, "/* The engine may define the following macros:\n");
1941 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1942 for (i = 0;i < SHADERMODE_COUNT;i++)
1943 FS_Print(file, modeinfo[i].pretext);
1944 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1945 FS_Print(file, shaderpermutationinfo[i].pretext);
1946 FS_Print(file, "*/\n");
1947 FS_Print(file, text);
1949 Con_Printf("%s written\n", modeinfo[mode].filename);
1952 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1958 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1960 unsigned int permutation = 0;
1961 if (r_trippy.integer && !notrippy)
1962 permutation |= SHADERPERMUTATION_TRIPPY;
1963 permutation |= SHADERPERMUTATION_VIEWTINT;
1965 permutation |= SHADERPERMUTATION_DIFFUSE;
1967 permutation |= SHADERPERMUTATION_SPECULAR;
1968 if (texturemode == GL_MODULATE)
1969 permutation |= SHADERPERMUTATION_COLORMAPPING;
1970 else if (texturemode == GL_ADD)
1971 permutation |= SHADERPERMUTATION_GLOW;
1972 else if (texturemode == GL_DECAL)
1973 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1974 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1975 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1976 if (suppresstexalpha)
1977 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1979 texturemode = GL_MODULATE;
1980 if (vid.allowalphatocoverage)
1981 GL_AlphaToCoverage(false);
1982 switch (vid.renderpath)
1984 case RENDERPATH_D3D9:
1986 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1987 R_Mesh_TexBind(GL20TU_FIRST , first );
1988 R_Mesh_TexBind(GL20TU_SECOND, second);
1989 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1990 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1993 case RENDERPATH_D3D10:
1994 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1996 case RENDERPATH_D3D11:
1997 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1999 case RENDERPATH_GL20:
2000 case RENDERPATH_GLES2:
2001 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2002 if (r_glsl_permutation->tex_Texture_First >= 0)
2003 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2004 if (r_glsl_permutation->tex_Texture_Second >= 0)
2005 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2006 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2007 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2009 case RENDERPATH_GL13:
2010 case RENDERPATH_GLES1:
2011 R_Mesh_TexBind(0, first );
2012 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2013 R_Mesh_TexMatrix(0, NULL);
2014 R_Mesh_TexBind(1, second);
2017 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2018 R_Mesh_TexMatrix(1, NULL);
2021 case RENDERPATH_GL11:
2022 R_Mesh_TexBind(0, first );
2023 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2024 R_Mesh_TexMatrix(0, NULL);
2026 case RENDERPATH_SOFT:
2027 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2028 R_Mesh_TexBind(GL20TU_FIRST , first );
2029 R_Mesh_TexBind(GL20TU_SECOND, second);
2034 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2036 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2039 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2041 unsigned int permutation = 0;
2042 if (r_trippy.integer && !notrippy)
2043 permutation |= SHADERPERMUTATION_TRIPPY;
2045 permutation |= SHADERPERMUTATION_DEPTHRGB;
2047 permutation |= SHADERPERMUTATION_SKELETAL;
2049 if (vid.allowalphatocoverage)
2050 GL_AlphaToCoverage(false);
2051 switch (vid.renderpath)
2053 case RENDERPATH_D3D9:
2055 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2058 case RENDERPATH_D3D10:
2059 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2061 case RENDERPATH_D3D11:
2062 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2064 case RENDERPATH_GL20:
2065 case RENDERPATH_GLES2:
2066 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2067 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);
2069 case RENDERPATH_GL13:
2070 case RENDERPATH_GLES1:
2071 R_Mesh_TexBind(0, 0);
2072 R_Mesh_TexBind(1, 0);
2074 case RENDERPATH_GL11:
2075 R_Mesh_TexBind(0, 0);
2077 case RENDERPATH_SOFT:
2078 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2083 extern qboolean r_shadow_usingdeferredprepass;
2084 extern rtexture_t *r_shadow_attenuationgradienttexture;
2085 extern rtexture_t *r_shadow_attenuation2dtexture;
2086 extern rtexture_t *r_shadow_attenuation3dtexture;
2087 extern qboolean r_shadow_usingshadowmap2d;
2088 extern qboolean r_shadow_usingshadowmaportho;
2089 extern float r_shadow_shadowmap_texturescale[2];
2090 extern float r_shadow_shadowmap_parameters[4];
2091 extern qboolean r_shadow_shadowmapvsdct;
2092 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2093 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2094 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2095 extern matrix4x4_t r_shadow_shadowmapmatrix;
2096 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2097 extern int r_shadow_prepass_width;
2098 extern int r_shadow_prepass_height;
2099 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2100 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2101 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2102 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2104 #define BLENDFUNC_ALLOWS_COLORMOD 1
2105 #define BLENDFUNC_ALLOWS_FOG 2
2106 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2107 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2108 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2109 static int R_BlendFuncFlags(int src, int dst)
2113 // a blendfunc allows colormod if:
2114 // a) it can never keep the destination pixel invariant, or
2115 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2116 // this is to prevent unintended side effects from colormod
2118 // a blendfunc allows fog if:
2119 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2120 // this is to prevent unintended side effects from fog
2122 // these checks are the output of fogeval.pl
2124 r |= BLENDFUNC_ALLOWS_COLORMOD;
2125 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2126 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2127 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2128 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2129 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2130 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2131 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2132 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2133 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2134 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2135 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2136 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2137 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2138 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2139 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2140 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2141 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2142 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2143 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2144 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2145 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2150 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)
2152 // select a permutation of the lighting shader appropriate to this
2153 // combination of texture, entity, light source, and fogging, only use the
2154 // minimum features necessary to avoid wasting rendering time in the
2155 // fragment shader on features that are not being used
2156 unsigned int permutation = 0;
2157 unsigned int mode = 0;
2159 static float dummy_colormod[3] = {1, 1, 1};
2160 float *colormod = rsurface.colormod;
2162 matrix4x4_t tempmatrix;
2163 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2164 if (r_trippy.integer && !notrippy)
2165 permutation |= SHADERPERMUTATION_TRIPPY;
2166 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2167 permutation |= SHADERPERMUTATION_ALPHAKILL;
2168 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2169 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2170 if (rsurfacepass == RSURFPASS_BACKGROUND)
2172 // distorted background
2173 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2175 mode = SHADERMODE_WATER;
2176 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2177 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2178 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2180 // this is the right thing to do for wateralpha
2181 GL_BlendFunc(GL_ONE, GL_ZERO);
2182 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2186 // this is the right thing to do for entity alpha
2187 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2188 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2191 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2193 mode = SHADERMODE_REFRACTION;
2194 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2195 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2196 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2197 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2201 mode = SHADERMODE_GENERIC;
2202 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2203 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2204 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2206 if (vid.allowalphatocoverage)
2207 GL_AlphaToCoverage(false);
2209 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2211 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2213 switch(rsurface.texture->offsetmapping)
2215 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2216 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2217 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2218 case OFFSETMAPPING_OFF: break;
2221 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2222 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2223 // normalmap (deferred prepass), may use alpha test on diffuse
2224 mode = SHADERMODE_DEFERREDGEOMETRY;
2225 GL_BlendFunc(GL_ONE, GL_ZERO);
2226 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2227 if (vid.allowalphatocoverage)
2228 GL_AlphaToCoverage(false);
2230 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2232 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2234 switch(rsurface.texture->offsetmapping)
2236 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2237 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2238 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2239 case OFFSETMAPPING_OFF: break;
2242 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2243 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2244 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2245 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2247 mode = SHADERMODE_LIGHTSOURCE;
2248 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2249 permutation |= SHADERPERMUTATION_CUBEFILTER;
2250 if (diffusescale > 0)
2251 permutation |= SHADERPERMUTATION_DIFFUSE;
2252 if (specularscale > 0)
2253 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2254 if (r_refdef.fogenabled)
2255 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2256 if (rsurface.texture->colormapping)
2257 permutation |= SHADERPERMUTATION_COLORMAPPING;
2258 if (r_shadow_usingshadowmap2d)
2260 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2261 if(r_shadow_shadowmapvsdct)
2262 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2264 if (r_shadow_shadowmap2ddepthbuffer)
2265 permutation |= SHADERPERMUTATION_DEPTHRGB;
2267 if (rsurface.texture->reflectmasktexture)
2268 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2269 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2270 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2271 if (vid.allowalphatocoverage)
2272 GL_AlphaToCoverage(false);
2274 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2276 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2278 switch(rsurface.texture->offsetmapping)
2280 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2281 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2282 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2283 case OFFSETMAPPING_OFF: break;
2286 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2287 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2288 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2289 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2290 // unshaded geometry (fullbright or ambient model lighting)
2291 mode = SHADERMODE_FLATCOLOR;
2292 ambientscale = diffusescale = specularscale = 0;
2293 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2294 permutation |= SHADERPERMUTATION_GLOW;
2295 if (r_refdef.fogenabled)
2296 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2297 if (rsurface.texture->colormapping)
2298 permutation |= SHADERPERMUTATION_COLORMAPPING;
2299 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2301 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2302 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2304 if (r_shadow_shadowmap2ddepthbuffer)
2305 permutation |= SHADERPERMUTATION_DEPTHRGB;
2307 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2308 permutation |= SHADERPERMUTATION_REFLECTION;
2309 if (rsurface.texture->reflectmasktexture)
2310 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2311 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2312 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2313 // when using alphatocoverage, we don't need alphakill
2314 if (vid.allowalphatocoverage)
2316 if (r_transparent_alphatocoverage.integer)
2318 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2319 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2322 GL_AlphaToCoverage(false);
2325 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2327 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2329 switch(rsurface.texture->offsetmapping)
2331 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2332 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2333 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2334 case OFFSETMAPPING_OFF: break;
2337 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2338 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2339 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2340 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2341 // directional model lighting
2342 mode = SHADERMODE_LIGHTDIRECTION;
2343 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2344 permutation |= SHADERPERMUTATION_GLOW;
2345 permutation |= SHADERPERMUTATION_DIFFUSE;
2346 if (specularscale > 0)
2347 permutation |= SHADERPERMUTATION_SPECULAR;
2348 if (r_refdef.fogenabled)
2349 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2350 if (rsurface.texture->colormapping)
2351 permutation |= SHADERPERMUTATION_COLORMAPPING;
2352 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2354 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2355 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2357 if (r_shadow_shadowmap2ddepthbuffer)
2358 permutation |= SHADERPERMUTATION_DEPTHRGB;
2360 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2361 permutation |= SHADERPERMUTATION_REFLECTION;
2362 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2363 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2364 if (rsurface.texture->reflectmasktexture)
2365 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2366 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2368 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2369 if (r_shadow_bouncegriddirectional)
2370 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2372 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2373 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2374 // when using alphatocoverage, we don't need alphakill
2375 if (vid.allowalphatocoverage)
2377 if (r_transparent_alphatocoverage.integer)
2379 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2380 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2383 GL_AlphaToCoverage(false);
2386 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2388 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2390 switch(rsurface.texture->offsetmapping)
2392 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2393 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2394 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2395 case OFFSETMAPPING_OFF: break;
2398 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2399 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2400 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2401 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2402 // ambient model lighting
2403 mode = SHADERMODE_LIGHTDIRECTION;
2404 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2405 permutation |= SHADERPERMUTATION_GLOW;
2406 if (r_refdef.fogenabled)
2407 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2408 if (rsurface.texture->colormapping)
2409 permutation |= SHADERPERMUTATION_COLORMAPPING;
2410 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2412 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2413 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2415 if (r_shadow_shadowmap2ddepthbuffer)
2416 permutation |= SHADERPERMUTATION_DEPTHRGB;
2418 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2419 permutation |= SHADERPERMUTATION_REFLECTION;
2420 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2421 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2422 if (rsurface.texture->reflectmasktexture)
2423 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2424 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2426 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2427 if (r_shadow_bouncegriddirectional)
2428 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2430 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2431 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2432 // when using alphatocoverage, we don't need alphakill
2433 if (vid.allowalphatocoverage)
2435 if (r_transparent_alphatocoverage.integer)
2437 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2438 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2441 GL_AlphaToCoverage(false);
2446 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2448 switch(rsurface.texture->offsetmapping)
2450 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2451 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2452 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2453 case OFFSETMAPPING_OFF: break;
2456 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2457 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2458 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2459 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2461 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2462 permutation |= SHADERPERMUTATION_GLOW;
2463 if (r_refdef.fogenabled)
2464 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2465 if (rsurface.texture->colormapping)
2466 permutation |= SHADERPERMUTATION_COLORMAPPING;
2467 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2469 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2470 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2472 if (r_shadow_shadowmap2ddepthbuffer)
2473 permutation |= SHADERPERMUTATION_DEPTHRGB;
2475 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2476 permutation |= SHADERPERMUTATION_REFLECTION;
2477 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2478 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2479 if (rsurface.texture->reflectmasktexture)
2480 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2481 if (FAKELIGHT_ENABLED)
2483 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2484 mode = SHADERMODE_FAKELIGHT;
2485 permutation |= SHADERPERMUTATION_DIFFUSE;
2486 if (specularscale > 0)
2487 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2489 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2491 // deluxemapping (light direction texture)
2492 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2493 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2495 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2496 permutation |= SHADERPERMUTATION_DIFFUSE;
2497 if (specularscale > 0)
2498 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2500 else if (r_glsl_deluxemapping.integer >= 2)
2502 // fake deluxemapping (uniform light direction in tangentspace)
2503 if (rsurface.uselightmaptexture)
2504 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2506 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2507 permutation |= SHADERPERMUTATION_DIFFUSE;
2508 if (specularscale > 0)
2509 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2511 else if (rsurface.uselightmaptexture)
2513 // ordinary lightmapping (q1bsp, q3bsp)
2514 mode = SHADERMODE_LIGHTMAP;
2518 // ordinary vertex coloring (q3bsp)
2519 mode = SHADERMODE_VERTEXCOLOR;
2521 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2523 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2524 if (r_shadow_bouncegriddirectional)
2525 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2527 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2528 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2529 // when using alphatocoverage, we don't need alphakill
2530 if (vid.allowalphatocoverage)
2532 if (r_transparent_alphatocoverage.integer)
2534 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2535 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2538 GL_AlphaToCoverage(false);
2541 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2542 colormod = dummy_colormod;
2543 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2544 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2545 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2546 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2547 switch(vid.renderpath)
2549 case RENDERPATH_D3D9:
2551 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);
2552 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2553 R_SetupShader_SetPermutationHLSL(mode, permutation);
2554 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2555 if (mode == SHADERMODE_LIGHTSOURCE)
2557 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2558 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2562 if (mode == SHADERMODE_LIGHTDIRECTION)
2564 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2567 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2568 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2569 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2570 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2571 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2573 if (mode == SHADERMODE_LIGHTSOURCE)
2575 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2576 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2577 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2578 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2579 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2581 // additive passes are only darkened by fog, not tinted
2582 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2583 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2587 if (mode == SHADERMODE_FLATCOLOR)
2589 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2591 else if (mode == SHADERMODE_LIGHTDIRECTION)
2593 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]);
2594 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2595 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);
2596 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2597 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2598 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2599 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2603 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2604 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2605 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);
2606 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2607 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2609 // additive passes are only darkened by fog, not tinted
2610 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2611 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2613 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2614 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);
2615 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2616 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2617 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2618 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2619 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2620 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2621 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2622 if (mode == SHADERMODE_WATER)
2623 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2625 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2626 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2627 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2628 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));
2629 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2630 if (rsurface.texture->pantstexture)
2631 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2633 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2634 if (rsurface.texture->shirttexture)
2635 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2637 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2638 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2639 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2640 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2641 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2642 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2643 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2644 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2645 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2646 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2648 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2649 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2650 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2651 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2653 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2654 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2655 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2656 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2657 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2658 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2659 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2660 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2661 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2662 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2663 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2664 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2665 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2666 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2667 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2668 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2669 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2670 if (rsurfacepass == RSURFPASS_BACKGROUND)
2672 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2673 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2674 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2678 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2680 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2681 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2682 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2683 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2685 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2686 if (rsurface.rtlight)
2688 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2689 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2694 case RENDERPATH_D3D10:
2695 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2697 case RENDERPATH_D3D11:
2698 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2700 case RENDERPATH_GL20:
2701 case RENDERPATH_GLES2:
2702 if (!vid.useinterleavedarrays)
2704 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);
2705 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2706 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2707 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2708 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2709 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2710 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2711 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2712 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2713 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2714 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2718 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);
2719 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2721 // this has to be after RSurf_PrepareVerticesForBatch
2722 if (rsurface.batchskeletaltransform3x4buffer)
2723 permutation |= SHADERPERMUTATION_SKELETAL;
2724 R_SetupShader_SetPermutationGLSL(mode, permutation);
2725 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);
2726 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2727 if (mode == SHADERMODE_LIGHTSOURCE)
2729 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2730 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2731 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2732 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2733 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2734 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);
2736 // additive passes are only darkened by fog, not tinted
2737 if (r_glsl_permutation->loc_FogColor >= 0)
2738 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2739 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);
2743 if (mode == SHADERMODE_FLATCOLOR)
2745 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2747 else if (mode == SHADERMODE_LIGHTDIRECTION)
2749 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]);
2750 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]);
2751 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);
2752 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2753 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2754 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]);
2755 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]);
2759 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]);
2760 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]);
2761 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);
2762 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2763 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2765 // additive passes are only darkened by fog, not tinted
2766 if (r_glsl_permutation->loc_FogColor >= 0)
2768 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2769 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2771 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2773 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);
2774 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]);
2775 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]);
2776 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]);
2777 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]);
2778 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2779 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2780 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);
2781 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]);
2783 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2784 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2785 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2786 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]);
2787 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]);
2789 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2790 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));
2791 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2792 if (r_glsl_permutation->loc_Color_Pants >= 0)
2794 if (rsurface.texture->pantstexture)
2795 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2797 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2799 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2801 if (rsurface.texture->shirttexture)
2802 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2804 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2806 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]);
2807 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2808 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2809 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2810 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2811 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2812 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2813 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2814 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2816 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);
2817 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2818 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]);
2819 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2820 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);}
2821 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2823 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2824 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2825 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2826 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2827 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2828 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2829 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2830 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2831 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2832 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2833 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2834 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2835 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2836 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2837 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);
2838 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2839 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2840 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2841 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2842 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2843 if (rsurfacepass == RSURFPASS_BACKGROUND)
2845 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);
2846 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);
2847 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);
2851 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);
2853 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2854 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2855 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2856 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2858 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2859 if (rsurface.rtlight)
2861 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2862 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2865 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2868 case RENDERPATH_GL11:
2869 case RENDERPATH_GL13:
2870 case RENDERPATH_GLES1:
2872 case RENDERPATH_SOFT:
2873 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);
2874 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2875 R_SetupShader_SetPermutationSoft(mode, permutation);
2876 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2877 if (mode == SHADERMODE_LIGHTSOURCE)
2879 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2880 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2881 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2882 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2883 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2884 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2886 // additive passes are only darkened by fog, not tinted
2887 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2888 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2892 if (mode == SHADERMODE_FLATCOLOR)
2894 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2896 else if (mode == SHADERMODE_LIGHTDIRECTION)
2898 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]);
2899 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2900 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);
2901 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2902 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2903 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]);
2904 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2908 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2909 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2910 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);
2911 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2912 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2914 // additive passes are only darkened by fog, not tinted
2915 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2916 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2918 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2919 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);
2920 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]);
2921 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]);
2922 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]);
2923 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]);
2924 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2925 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2926 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2927 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2929 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2930 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2931 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2932 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2933 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]);
2935 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2936 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));
2937 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2938 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2940 if (rsurface.texture->pantstexture)
2941 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2943 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2945 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2947 if (rsurface.texture->shirttexture)
2948 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2950 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2952 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2953 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2954 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2955 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2956 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2957 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2958 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2959 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2960 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2962 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2963 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2964 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2965 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2967 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2968 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2969 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2970 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2971 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2972 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2973 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2974 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2975 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2976 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2977 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2978 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2979 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2980 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2981 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2982 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2983 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2984 if (rsurfacepass == RSURFPASS_BACKGROUND)
2986 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2987 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2988 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2992 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2994 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2995 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2996 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2997 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2999 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3000 if (rsurface.rtlight)
3002 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3003 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3010 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3012 // select a permutation of the lighting shader appropriate to this
3013 // combination of texture, entity, light source, and fogging, only use the
3014 // minimum features necessary to avoid wasting rendering time in the
3015 // fragment shader on features that are not being used
3016 unsigned int permutation = 0;
3017 unsigned int mode = 0;
3018 const float *lightcolorbase = rtlight->currentcolor;
3019 float ambientscale = rtlight->ambientscale;
3020 float diffusescale = rtlight->diffusescale;
3021 float specularscale = rtlight->specularscale;
3022 // this is the location of the light in view space
3023 vec3_t viewlightorigin;
3024 // this transforms from view space (camera) to light space (cubemap)
3025 matrix4x4_t viewtolight;
3026 matrix4x4_t lighttoview;
3027 float viewtolight16f[16];
3029 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3030 if (rtlight->currentcubemap != r_texture_whitecube)
3031 permutation |= SHADERPERMUTATION_CUBEFILTER;
3032 if (diffusescale > 0)
3033 permutation |= SHADERPERMUTATION_DIFFUSE;
3034 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3035 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3036 if (r_shadow_usingshadowmap2d)
3038 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3039 if (r_shadow_shadowmapvsdct)
3040 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3042 if (r_shadow_shadowmap2ddepthbuffer)
3043 permutation |= SHADERPERMUTATION_DEPTHRGB;
3045 if (vid.allowalphatocoverage)
3046 GL_AlphaToCoverage(false);
3047 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3048 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3049 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3050 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3051 switch(vid.renderpath)
3053 case RENDERPATH_D3D9:
3055 R_SetupShader_SetPermutationHLSL(mode, permutation);
3056 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3057 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3058 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3059 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3060 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3061 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3062 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3063 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);
3064 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3065 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3067 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3068 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3069 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3070 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3071 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3074 case RENDERPATH_D3D10:
3075 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3077 case RENDERPATH_D3D11:
3078 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3080 case RENDERPATH_GL20:
3081 case RENDERPATH_GLES2:
3082 R_SetupShader_SetPermutationGLSL(mode, permutation);
3083 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3084 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3085 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3086 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3087 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3088 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]);
3089 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]);
3090 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);
3091 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]);
3092 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3094 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3095 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3096 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3097 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3098 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3100 case RENDERPATH_GL11:
3101 case RENDERPATH_GL13:
3102 case RENDERPATH_GLES1:
3104 case RENDERPATH_SOFT:
3105 R_SetupShader_SetPermutationGLSL(mode, permutation);
3106 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3107 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3108 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3109 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3110 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3111 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3112 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]);
3113 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);
3114 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3115 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3117 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3118 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3119 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3120 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3121 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3126 #define SKINFRAME_HASH 1024
3130 int loadsequence; // incremented each level change
3131 memexpandablearray_t array;
3132 skinframe_t *hash[SKINFRAME_HASH];
3135 r_skinframe_t r_skinframe;
3137 void R_SkinFrame_PrepareForPurge(void)
3139 r_skinframe.loadsequence++;
3140 // wrap it without hitting zero
3141 if (r_skinframe.loadsequence >= 200)
3142 r_skinframe.loadsequence = 1;
3145 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3149 // mark the skinframe as used for the purging code
3150 skinframe->loadsequence = r_skinframe.loadsequence;
3153 void R_SkinFrame_Purge(void)
3157 for (i = 0;i < SKINFRAME_HASH;i++)
3159 for (s = r_skinframe.hash[i];s;s = s->next)
3161 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3163 if (s->merged == s->base)
3165 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3166 R_PurgeTexture(s->stain );s->stain = NULL;
3167 R_PurgeTexture(s->merged);s->merged = NULL;
3168 R_PurgeTexture(s->base );s->base = NULL;
3169 R_PurgeTexture(s->pants );s->pants = NULL;
3170 R_PurgeTexture(s->shirt );s->shirt = NULL;
3171 R_PurgeTexture(s->nmap );s->nmap = NULL;
3172 R_PurgeTexture(s->gloss );s->gloss = NULL;
3173 R_PurgeTexture(s->glow );s->glow = NULL;
3174 R_PurgeTexture(s->fog );s->fog = NULL;
3175 R_PurgeTexture(s->reflect);s->reflect = NULL;
3176 s->loadsequence = 0;
3182 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3184 char basename[MAX_QPATH];
3186 Image_StripImageExtension(name, basename, sizeof(basename));
3188 if( last == NULL ) {
3190 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3191 item = r_skinframe.hash[hashindex];
3196 // linearly search through the hash bucket
3197 for( ; item ; item = item->next ) {
3198 if( !strcmp( item->basename, basename ) ) {
3205 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3209 char basename[MAX_QPATH];
3211 Image_StripImageExtension(name, basename, sizeof(basename));
3213 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3214 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3215 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3219 rtexture_t *dyntexture;
3220 // check whether its a dynamic texture
3221 dyntexture = CL_GetDynTexture( basename );
3222 if (!add && !dyntexture)
3224 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3225 memset(item, 0, sizeof(*item));
3226 strlcpy(item->basename, basename, sizeof(item->basename));
3227 item->base = dyntexture; // either NULL or dyntexture handle
3228 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3229 item->comparewidth = comparewidth;
3230 item->compareheight = compareheight;
3231 item->comparecrc = comparecrc;
3232 item->next = r_skinframe.hash[hashindex];
3233 r_skinframe.hash[hashindex] = item;
3235 else if (textureflags & TEXF_FORCE_RELOAD)
3237 rtexture_t *dyntexture;
3238 // check whether its a dynamic texture
3239 dyntexture = CL_GetDynTexture( basename );
3240 if (!add && !dyntexture)
3242 if (item->merged == item->base)
3243 item->merged = NULL;
3244 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3245 R_PurgeTexture(item->stain );item->stain = NULL;
3246 R_PurgeTexture(item->merged);item->merged = NULL;
3247 R_PurgeTexture(item->base );item->base = NULL;
3248 R_PurgeTexture(item->pants );item->pants = NULL;
3249 R_PurgeTexture(item->shirt );item->shirt = NULL;
3250 R_PurgeTexture(item->nmap );item->nmap = NULL;
3251 R_PurgeTexture(item->gloss );item->gloss = NULL;
3252 R_PurgeTexture(item->glow );item->glow = NULL;
3253 R_PurgeTexture(item->fog );item->fog = NULL;
3254 R_PurgeTexture(item->reflect);item->reflect = NULL;
3255 item->loadsequence = 0;
3257 else if( item->base == NULL )
3259 rtexture_t *dyntexture;
3260 // check whether its a dynamic texture
3261 // 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]
3262 dyntexture = CL_GetDynTexture( basename );
3263 item->base = dyntexture; // either NULL or dyntexture handle
3266 R_SkinFrame_MarkUsed(item);
3270 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3272 unsigned long long avgcolor[5], wsum; \
3280 for(pix = 0; pix < cnt; ++pix) \
3283 for(comp = 0; comp < 3; ++comp) \
3285 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3288 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3290 for(comp = 0; comp < 3; ++comp) \
3291 avgcolor[comp] += getpixel * w; \
3294 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3295 avgcolor[4] += getpixel; \
3297 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3299 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3300 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3301 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3302 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3305 extern cvar_t gl_picmip;
3306 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3309 unsigned char *pixels;
3310 unsigned char *bumppixels;
3311 unsigned char *basepixels = NULL;
3312 int basepixels_width = 0;
3313 int basepixels_height = 0;
3314 skinframe_t *skinframe;
3315 rtexture_t *ddsbase = NULL;
3316 qboolean ddshasalpha = false;
3317 float ddsavgcolor[4];
3318 char basename[MAX_QPATH];
3319 int miplevel = R_PicmipForFlags(textureflags);
3320 int savemiplevel = miplevel;
3324 if (cls.state == ca_dedicated)
3327 // return an existing skinframe if already loaded
3328 // if loading of the first image fails, don't make a new skinframe as it
3329 // would cause all future lookups of this to be missing
3330 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3331 if (skinframe && skinframe->base)
3334 Image_StripImageExtension(name, basename, sizeof(basename));
3336 // check for DDS texture file first
3337 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3339 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3340 if (basepixels == NULL)
3344 // FIXME handle miplevel
3346 if (developer_loading.integer)
3347 Con_Printf("loading skin \"%s\"\n", name);
3349 // we've got some pixels to store, so really allocate this new texture now
3351 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3352 textureflags &= ~TEXF_FORCE_RELOAD;
3353 skinframe->stain = NULL;
3354 skinframe->merged = NULL;
3355 skinframe->base = NULL;
3356 skinframe->pants = NULL;
3357 skinframe->shirt = NULL;
3358 skinframe->nmap = NULL;
3359 skinframe->gloss = NULL;
3360 skinframe->glow = NULL;
3361 skinframe->fog = NULL;
3362 skinframe->reflect = NULL;
3363 skinframe->hasalpha = false;
3367 skinframe->base = ddsbase;
3368 skinframe->hasalpha = ddshasalpha;
3369 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3370 if (r_loadfog && skinframe->hasalpha)
3371 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);
3372 //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]);
3376 basepixels_width = image_width;
3377 basepixels_height = image_height;
3378 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);
3379 if (textureflags & TEXF_ALPHA)
3381 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3383 if (basepixels[j] < 255)
3385 skinframe->hasalpha = true;
3389 if (r_loadfog && skinframe->hasalpha)
3391 // has transparent pixels
3392 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3393 for (j = 0;j < image_width * image_height * 4;j += 4)
3398 pixels[j+3] = basepixels[j+3];
3400 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);
3404 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3406 //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]);
3407 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3408 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3409 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3410 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3416 mymiplevel = savemiplevel;
3417 if (r_loadnormalmap)
3418 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);
3419 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3421 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3422 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3423 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3424 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3427 // _norm is the name used by tenebrae and has been adopted as standard
3428 if (r_loadnormalmap && skinframe->nmap == NULL)
3430 mymiplevel = savemiplevel;
3431 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3433 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);
3437 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3439 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3440 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3441 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);
3443 Mem_Free(bumppixels);
3445 else if (r_shadow_bumpscale_basetexture.value > 0)
3447 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3448 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3449 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);
3453 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3454 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3458 // _luma is supported only for tenebrae compatibility
3459 // _glow is the preferred name
3460 mymiplevel = savemiplevel;
3461 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))))
3463 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);
3465 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3466 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3468 Mem_Free(pixels);pixels = NULL;
3471 mymiplevel = savemiplevel;
3472 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3474 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);
3476 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3477 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3483 mymiplevel = savemiplevel;
3484 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3486 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);
3488 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3489 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3495 mymiplevel = savemiplevel;
3496 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3498 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);
3500 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3501 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3507 mymiplevel = savemiplevel;
3508 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3510 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);
3512 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3513 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3520 Mem_Free(basepixels);
3525 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3526 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3529 unsigned char *temp1, *temp2;
3530 skinframe_t *skinframe;
3533 if (cls.state == ca_dedicated)
3536 // if already loaded just return it, otherwise make a new skinframe
3537 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3538 if (skinframe->base)
3540 textureflags &= ~TEXF_FORCE_RELOAD;
3542 skinframe->stain = NULL;
3543 skinframe->merged = NULL;
3544 skinframe->base = NULL;
3545 skinframe->pants = NULL;
3546 skinframe->shirt = NULL;
3547 skinframe->nmap = NULL;
3548 skinframe->gloss = NULL;
3549 skinframe->glow = NULL;
3550 skinframe->fog = NULL;
3551 skinframe->reflect = NULL;
3552 skinframe->hasalpha = false;
3554 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3558 if (developer_loading.integer)
3559 Con_Printf("loading 32bit skin \"%s\"\n", name);
3561 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3563 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3564 temp2 = temp1 + width * height * 4;
3565 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3566 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);
3569 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3570 if (textureflags & TEXF_ALPHA)
3572 for (i = 3;i < width * height * 4;i += 4)
3574 if (skindata[i] < 255)
3576 skinframe->hasalpha = true;
3580 if (r_loadfog && skinframe->hasalpha)
3582 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3583 memcpy(fogpixels, skindata, width * height * 4);
3584 for (i = 0;i < width * height * 4;i += 4)
3585 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3586 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3587 Mem_Free(fogpixels);
3591 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3592 //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]);
3597 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3601 skinframe_t *skinframe;
3603 if (cls.state == ca_dedicated)
3606 // if already loaded just return it, otherwise make a new skinframe
3607 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3608 if (skinframe->base)
3610 //textureflags &= ~TEXF_FORCE_RELOAD;
3612 skinframe->stain = NULL;
3613 skinframe->merged = NULL;
3614 skinframe->base = NULL;
3615 skinframe->pants = NULL;
3616 skinframe->shirt = NULL;
3617 skinframe->nmap = NULL;
3618 skinframe->gloss = NULL;
3619 skinframe->glow = NULL;
3620 skinframe->fog = NULL;
3621 skinframe->reflect = NULL;
3622 skinframe->hasalpha = false;
3624 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3628 if (developer_loading.integer)
3629 Con_Printf("loading quake skin \"%s\"\n", name);
3631 // 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)
3632 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3633 memcpy(skinframe->qpixels, skindata, width*height);
3634 skinframe->qwidth = width;
3635 skinframe->qheight = height;
3638 for (i = 0;i < width * height;i++)
3639 featuresmask |= palette_featureflags[skindata[i]];
3641 skinframe->hasalpha = false;
3642 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3643 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3644 skinframe->qgeneratemerged = true;
3645 skinframe->qgeneratebase = skinframe->qhascolormapping;
3646 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3648 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3649 //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]);
3654 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3658 unsigned char *skindata;
3661 if (!skinframe->qpixels)
3664 if (!skinframe->qhascolormapping)
3665 colormapped = false;
3669 if (!skinframe->qgeneratebase)
3674 if (!skinframe->qgeneratemerged)
3678 width = skinframe->qwidth;
3679 height = skinframe->qheight;
3680 skindata = skinframe->qpixels;
3682 if (skinframe->qgeneratenmap)
3684 unsigned char *temp1, *temp2;
3685 skinframe->qgeneratenmap = false;
3686 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3687 temp2 = temp1 + width * height * 4;
3688 // use either a custom palette or the quake palette
3689 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3690 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3691 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);
3695 if (skinframe->qgenerateglow)
3697 skinframe->qgenerateglow = false;
3698 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
3703 skinframe->qgeneratebase = false;
3704 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);
3705 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);
3706 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);
3710 skinframe->qgeneratemerged = false;
3711 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);
3714 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3716 Mem_Free(skinframe->qpixels);
3717 skinframe->qpixels = NULL;
3721 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)
3724 skinframe_t *skinframe;
3727 if (cls.state == ca_dedicated)
3730 // if already loaded just return it, otherwise make a new skinframe
3731 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3732 if (skinframe->base)
3734 textureflags &= ~TEXF_FORCE_RELOAD;
3736 skinframe->stain = NULL;
3737 skinframe->merged = NULL;
3738 skinframe->base = NULL;
3739 skinframe->pants = NULL;
3740 skinframe->shirt = NULL;
3741 skinframe->nmap = NULL;
3742 skinframe->gloss = NULL;
3743 skinframe->glow = NULL;
3744 skinframe->fog = NULL;
3745 skinframe->reflect = NULL;
3746 skinframe->hasalpha = false;
3748 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3752 if (developer_loading.integer)
3753 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3755 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3756 if (textureflags & TEXF_ALPHA)
3758 for (i = 0;i < width * height;i++)
3760 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3762 skinframe->hasalpha = true;
3766 if (r_loadfog && skinframe->hasalpha)
3767 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3770 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3771 //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]);
3776 skinframe_t *R_SkinFrame_LoadMissing(void)
3778 skinframe_t *skinframe;
3780 if (cls.state == ca_dedicated)
3783 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3784 skinframe->stain = NULL;
3785 skinframe->merged = NULL;
3786 skinframe->base = NULL;
3787 skinframe->pants = NULL;
3788 skinframe->shirt = NULL;
3789 skinframe->nmap = NULL;
3790 skinframe->gloss = NULL;
3791 skinframe->glow = NULL;
3792 skinframe->fog = NULL;
3793 skinframe->reflect = NULL;
3794 skinframe->hasalpha = false;
3796 skinframe->avgcolor[0] = rand() / RAND_MAX;
3797 skinframe->avgcolor[1] = rand() / RAND_MAX;
3798 skinframe->avgcolor[2] = rand() / RAND_MAX;
3799 skinframe->avgcolor[3] = 1;
3804 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3805 typedef struct suffixinfo_s
3808 qboolean flipx, flipy, flipdiagonal;
3811 static suffixinfo_t suffix[3][6] =
3814 {"px", false, false, false},
3815 {"nx", false, false, false},
3816 {"py", false, false, false},
3817 {"ny", false, false, false},
3818 {"pz", false, false, false},
3819 {"nz", false, false, false}
3822 {"posx", false, false, false},
3823 {"negx", false, false, false},
3824 {"posy", false, false, false},
3825 {"negy", false, false, false},
3826 {"posz", false, false, false},
3827 {"negz", false, false, false}
3830 {"rt", true, false, true},
3831 {"lf", false, true, true},
3832 {"ft", true, true, false},
3833 {"bk", false, false, false},
3834 {"up", true, false, true},
3835 {"dn", true, false, true}
3839 static int componentorder[4] = {0, 1, 2, 3};
3841 static rtexture_t *R_LoadCubemap(const char *basename)
3843 int i, j, cubemapsize;
3844 unsigned char *cubemappixels, *image_buffer;
3845 rtexture_t *cubemaptexture;
3847 // must start 0 so the first loadimagepixels has no requested width/height
3849 cubemappixels = NULL;
3850 cubemaptexture = NULL;
3851 // keep trying different suffix groups (posx, px, rt) until one loads
3852 for (j = 0;j < 3 && !cubemappixels;j++)
3854 // load the 6 images in the suffix group
3855 for (i = 0;i < 6;i++)
3857 // generate an image name based on the base and and suffix
3858 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3860 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3862 // an image loaded, make sure width and height are equal
3863 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3865 // if this is the first image to load successfully, allocate the cubemap memory
3866 if (!cubemappixels && image_width >= 1)
3868 cubemapsize = image_width;
3869 // note this clears to black, so unavailable sides are black
3870 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3872 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3874 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);
3877 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3879 Mem_Free(image_buffer);
3883 // if a cubemap loaded, upload it
3886 if (developer_loading.integer)
3887 Con_Printf("loading cubemap \"%s\"\n", basename);
3889 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);
3890 Mem_Free(cubemappixels);
3894 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3895 if (developer_loading.integer)
3897 Con_Printf("(tried tried images ");
3898 for (j = 0;j < 3;j++)
3899 for (i = 0;i < 6;i++)
3900 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3901 Con_Print(" and was unable to find any of them).\n");
3904 return cubemaptexture;
3907 rtexture_t *R_GetCubemap(const char *basename)
3910 for (i = 0;i < r_texture_numcubemaps;i++)
3911 if (r_texture_cubemaps[i] != NULL)
3912 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3913 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3914 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3915 return r_texture_whitecube;
3916 r_texture_numcubemaps++;
3917 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3918 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3919 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3920 return r_texture_cubemaps[i]->texture;
3923 static void R_Main_FreeViewCache(void)
3925 if (r_refdef.viewcache.entityvisible)
3926 Mem_Free(r_refdef.viewcache.entityvisible);
3927 if (r_refdef.viewcache.world_pvsbits)
3928 Mem_Free(r_refdef.viewcache.world_pvsbits);
3929 if (r_refdef.viewcache.world_leafvisible)
3930 Mem_Free(r_refdef.viewcache.world_leafvisible);
3931 if (r_refdef.viewcache.world_surfacevisible)
3932 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3933 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3936 static void R_Main_ResizeViewCache(void)
3938 int numentities = r_refdef.scene.numentities;
3939 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3940 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3941 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3942 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3943 if (r_refdef.viewcache.maxentities < numentities)
3945 r_refdef.viewcache.maxentities = numentities;
3946 if (r_refdef.viewcache.entityvisible)
3947 Mem_Free(r_refdef.viewcache.entityvisible);
3948 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3950 if (r_refdef.viewcache.world_numclusters != numclusters)
3952 r_refdef.viewcache.world_numclusters = numclusters;
3953 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3954 if (r_refdef.viewcache.world_pvsbits)
3955 Mem_Free(r_refdef.viewcache.world_pvsbits);
3956 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3958 if (r_refdef.viewcache.world_numleafs != numleafs)
3960 r_refdef.viewcache.world_numleafs = numleafs;
3961 if (r_refdef.viewcache.world_leafvisible)
3962 Mem_Free(r_refdef.viewcache.world_leafvisible);
3963 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3965 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3967 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3968 if (r_refdef.viewcache.world_surfacevisible)
3969 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3970 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3974 extern rtexture_t *loadingscreentexture;
3975 static void gl_main_start(void)
3977 loadingscreentexture = NULL;
3978 r_texture_blanknormalmap = NULL;
3979 r_texture_white = NULL;
3980 r_texture_grey128 = NULL;
3981 r_texture_black = NULL;
3982 r_texture_whitecube = NULL;
3983 r_texture_normalizationcube = NULL;
3984 r_texture_fogattenuation = NULL;
3985 r_texture_fogheighttexture = NULL;
3986 r_texture_gammaramps = NULL;
3987 r_texture_numcubemaps = 0;
3988 r_uniformbufferalignment = 32;
3990 r_loaddds = r_texture_dds_load.integer != 0;
3991 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3993 switch(vid.renderpath)
3995 case RENDERPATH_GL20:
3996 case RENDERPATH_D3D9:
3997 case RENDERPATH_D3D10:
3998 case RENDERPATH_D3D11:
3999 case RENDERPATH_SOFT:
4000 case RENDERPATH_GLES2:
4001 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4002 Cvar_SetValueQuick(&gl_combine, 1);
4003 Cvar_SetValueQuick(&r_glsl, 1);
4004 r_loadnormalmap = true;
4007 if (vid.support.arb_uniform_buffer_object)
4008 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4010 case RENDERPATH_GL13:
4011 case RENDERPATH_GLES1:
4012 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4013 Cvar_SetValueQuick(&gl_combine, 1);
4014 Cvar_SetValueQuick(&r_glsl, 0);
4015 r_loadnormalmap = false;
4016 r_loadgloss = false;
4019 case RENDERPATH_GL11:
4020 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4021 Cvar_SetValueQuick(&gl_combine, 0);
4022 Cvar_SetValueQuick(&r_glsl, 0);
4023 r_loadnormalmap = false;
4024 r_loadgloss = false;
4030 R_FrameData_Reset();
4031 R_BufferData_Reset();
4035 memset(r_queries, 0, sizeof(r_queries));
4037 r_qwskincache = NULL;
4038 r_qwskincache_size = 0;
4040 // due to caching of texture_t references, the collision cache must be reset
4041 Collision_Cache_Reset(true);
4043 // set up r_skinframe loading system for textures
4044 memset(&r_skinframe, 0, sizeof(r_skinframe));
4045 r_skinframe.loadsequence = 1;
4046 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4048 r_main_texturepool = R_AllocTexturePool();
4049 R_BuildBlankTextures();
4051 if (vid.support.arb_texture_cube_map)
4054 R_BuildNormalizationCube();
4056 r_texture_fogattenuation = NULL;
4057 r_texture_fogheighttexture = NULL;
4058 r_texture_gammaramps = NULL;
4059 //r_texture_fogintensity = NULL;
4060 memset(&r_fb, 0, sizeof(r_fb));
4061 r_glsl_permutation = NULL;
4062 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4063 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4064 glslshaderstring = NULL;
4066 r_hlsl_permutation = NULL;
4067 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4068 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4070 hlslshaderstring = NULL;
4071 memset(&r_svbsp, 0, sizeof (r_svbsp));
4073 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4074 r_texture_numcubemaps = 0;
4076 r_refdef.fogmasktable_density = 0;
4079 static void gl_main_shutdown(void)
4082 R_FrameData_Reset();
4083 R_BufferData_Reset();
4085 R_Main_FreeViewCache();
4087 switch(vid.renderpath)
4089 case RENDERPATH_GL11:
4090 case RENDERPATH_GL13:
4091 case RENDERPATH_GL20:
4092 case RENDERPATH_GLES1:
4093 case RENDERPATH_GLES2:
4094 #ifdef GL_SAMPLES_PASSED_ARB
4096 qglDeleteQueriesARB(r_maxqueries, r_queries);
4099 case RENDERPATH_D3D9:
4100 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4102 case RENDERPATH_D3D10:
4103 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4105 case RENDERPATH_D3D11:
4106 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4108 case RENDERPATH_SOFT:
4114 memset(r_queries, 0, sizeof(r_queries));
4116 r_qwskincache = NULL;
4117 r_qwskincache_size = 0;
4119 // clear out the r_skinframe state
4120 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4121 memset(&r_skinframe, 0, sizeof(r_skinframe));
4124 Mem_Free(r_svbsp.nodes);
4125 memset(&r_svbsp, 0, sizeof (r_svbsp));
4126 R_FreeTexturePool(&r_main_texturepool);
4127 loadingscreentexture = NULL;
4128 r_texture_blanknormalmap = NULL;
4129 r_texture_white = NULL;
4130 r_texture_grey128 = NULL;
4131 r_texture_black = NULL;
4132 r_texture_whitecube = NULL;
4133 r_texture_normalizationcube = NULL;
4134 r_texture_fogattenuation = NULL;
4135 r_texture_fogheighttexture = NULL;
4136 r_texture_gammaramps = NULL;
4137 r_texture_numcubemaps = 0;
4138 //r_texture_fogintensity = NULL;
4139 memset(&r_fb, 0, sizeof(r_fb));
4142 r_glsl_permutation = NULL;
4143 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4144 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4145 glslshaderstring = NULL;
4147 r_hlsl_permutation = NULL;
4148 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4149 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4151 hlslshaderstring = NULL;
4154 static void gl_main_newmap(void)
4156 // FIXME: move this code to client
4157 char *entities, entname[MAX_QPATH];
4159 Mem_Free(r_qwskincache);
4160 r_qwskincache = NULL;
4161 r_qwskincache_size = 0;
4164 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4165 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4167 CL_ParseEntityLump(entities);
4171 if (cl.worldmodel->brush.entities)
4172 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4174 R_Main_FreeViewCache();
4176 R_FrameData_Reset();
4177 R_BufferData_Reset();
4180 void GL_Main_Init(void)
4183 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4185 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4186 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4187 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4188 if (gamemode == GAME_NEHAHRA)
4190 Cvar_RegisterVariable (&gl_fogenable);
4191 Cvar_RegisterVariable (&gl_fogdensity);
4192 Cvar_RegisterVariable (&gl_fogred);
4193 Cvar_RegisterVariable (&gl_foggreen);
4194 Cvar_RegisterVariable (&gl_fogblue);
4195 Cvar_RegisterVariable (&gl_fogstart);
4196 Cvar_RegisterVariable (&gl_fogend);
4197 Cvar_RegisterVariable (&gl_skyclip);
4199 Cvar_RegisterVariable(&r_motionblur);
4200 Cvar_RegisterVariable(&r_damageblur);
4201 Cvar_RegisterVariable(&r_motionblur_averaging);
4202 Cvar_RegisterVariable(&r_motionblur_randomize);
4203 Cvar_RegisterVariable(&r_motionblur_minblur);
4204 Cvar_RegisterVariable(&r_motionblur_maxblur);
4205 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4206 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4207 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4208 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4209 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4210 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4211 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4212 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4213 Cvar_RegisterVariable(&r_equalize_entities_by);
4214 Cvar_RegisterVariable(&r_equalize_entities_to);
4215 Cvar_RegisterVariable(&r_depthfirst);
4216 Cvar_RegisterVariable(&r_useinfinitefarclip);
4217 Cvar_RegisterVariable(&r_farclip_base);
4218 Cvar_RegisterVariable(&r_farclip_world);
4219 Cvar_RegisterVariable(&r_nearclip);
4220 Cvar_RegisterVariable(&r_deformvertexes);
4221 Cvar_RegisterVariable(&r_transparent);
4222 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4223 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4224 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4225 Cvar_RegisterVariable(&r_showoverdraw);
4226 Cvar_RegisterVariable(&r_showbboxes);
4227 Cvar_RegisterVariable(&r_showsurfaces);
4228 Cvar_RegisterVariable(&r_showtris);
4229 Cvar_RegisterVariable(&r_shownormals);
4230 Cvar_RegisterVariable(&r_showlighting);
4231 Cvar_RegisterVariable(&r_showshadowvolumes);
4232 Cvar_RegisterVariable(&r_showcollisionbrushes);
4233 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4234 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4235 Cvar_RegisterVariable(&r_showdisabledepthtest);
4236 Cvar_RegisterVariable(&r_drawportals);
4237 Cvar_RegisterVariable(&r_drawentities);
4238 Cvar_RegisterVariable(&r_draw2d);
4239 Cvar_RegisterVariable(&r_drawworld);
4240 Cvar_RegisterVariable(&r_cullentities_trace);
4241 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4242 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4243 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4244 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4245 Cvar_RegisterVariable(&r_sortentities);
4246 Cvar_RegisterVariable(&r_drawviewmodel);
4247 Cvar_RegisterVariable(&r_drawexteriormodel);
4248 Cvar_RegisterVariable(&r_speeds);
4249 Cvar_RegisterVariable(&r_fullbrights);
4250 Cvar_RegisterVariable(&r_wateralpha);
4251 Cvar_RegisterVariable(&r_dynamic);
4252 Cvar_RegisterVariable(&r_fakelight);
4253 Cvar_RegisterVariable(&r_fakelight_intensity);
4254 Cvar_RegisterVariable(&r_fullbright);
4255 Cvar_RegisterVariable(&r_shadows);
4256 Cvar_RegisterVariable(&r_shadows_darken);
4257 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4258 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4259 Cvar_RegisterVariable(&r_shadows_throwdistance);
4260 Cvar_RegisterVariable(&r_shadows_throwdirection);
4261 Cvar_RegisterVariable(&r_shadows_focus);
4262 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4263 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4264 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4265 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4266 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4267 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4268 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4269 Cvar_RegisterVariable(&r_fog_exp2);
4270 Cvar_RegisterVariable(&r_fog_clear);
4271 Cvar_RegisterVariable(&r_drawfog);
4272 Cvar_RegisterVariable(&r_transparentdepthmasking);
4273 Cvar_RegisterVariable(&r_transparent_sortmindist);
4274 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4275 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4276 Cvar_RegisterVariable(&r_texture_dds_load);
4277 Cvar_RegisterVariable(&r_texture_dds_save);
4278 Cvar_RegisterVariable(&r_textureunits);
4279 Cvar_RegisterVariable(&gl_combine);
4280 Cvar_RegisterVariable(&r_usedepthtextures);
4281 Cvar_RegisterVariable(&r_viewfbo);
4282 Cvar_RegisterVariable(&r_viewscale);
4283 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4284 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4285 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4286 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4287 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4288 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4289 Cvar_RegisterVariable(&r_glsl);
4290 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4291 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4292 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4293 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4294 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4295 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4296 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4297 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4298 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4299 Cvar_RegisterVariable(&r_glsl_postprocess);
4300 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4301 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4302 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4303 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4304 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4305 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4306 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4307 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4308 Cvar_RegisterVariable(&r_celshading);
4309 Cvar_RegisterVariable(&r_celoutlines);
4311 Cvar_RegisterVariable(&r_water);
4312 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4313 Cvar_RegisterVariable(&r_water_clippingplanebias);
4314 Cvar_RegisterVariable(&r_water_refractdistort);
4315 Cvar_RegisterVariable(&r_water_reflectdistort);
4316 Cvar_RegisterVariable(&r_water_scissormode);
4317 Cvar_RegisterVariable(&r_water_lowquality);
4318 Cvar_RegisterVariable(&r_water_hideplayer);
4319 Cvar_RegisterVariable(&r_water_fbo);
4321 Cvar_RegisterVariable(&r_lerpsprites);
4322 Cvar_RegisterVariable(&r_lerpmodels);
4323 Cvar_RegisterVariable(&r_lerplightstyles);
4324 Cvar_RegisterVariable(&r_waterscroll);
4325 Cvar_RegisterVariable(&r_bloom);
4326 Cvar_RegisterVariable(&r_bloom_colorscale);
4327 Cvar_RegisterVariable(&r_bloom_brighten);
4328 Cvar_RegisterVariable(&r_bloom_blur);
4329 Cvar_RegisterVariable(&r_bloom_resolution);
4330 Cvar_RegisterVariable(&r_bloom_colorexponent);
4331 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4332 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4333 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4334 Cvar_RegisterVariable(&r_hdr_glowintensity);
4335 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4336 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4337 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4338 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4339 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4340 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4341 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4342 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4343 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4344 Cvar_RegisterVariable(&developer_texturelogging);
4345 Cvar_RegisterVariable(&gl_lightmaps);
4346 Cvar_RegisterVariable(&r_test);
4347 Cvar_RegisterVariable(&r_batch_multidraw);
4348 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4349 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4350 Cvar_RegisterVariable(&r_glsl_skeletal);
4351 Cvar_RegisterVariable(&r_glsl_saturation);
4352 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4353 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4354 Cvar_RegisterVariable(&r_framedatasize);
4355 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4356 Cvar_RegisterVariable(&r_bufferdatasize[i]);
4357 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4358 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4359 Cvar_SetValue("r_fullbrights", 0);
4360 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4363 void Render_Init(void)
4376 R_LightningBeams_Init();
4386 extern char *ENGINE_EXTENSIONS;
4389 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4390 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4391 gl_version = (const char *)qglGetString(GL_VERSION);
4392 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4396 if (!gl_platformextensions)
4397 gl_platformextensions = "";
4399 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4400 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4401 Con_Printf("GL_VERSION: %s\n", gl_version);
4402 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4403 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4405 VID_CheckExtensions();
4407 // LordHavoc: report supported extensions
4408 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4410 // clear to black (loading plaque will be seen over this)
4411 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4415 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4419 if (r_trippy.integer)
4421 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4423 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4426 p = r_refdef.view.frustum + i;
4431 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4435 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4439 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4443 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4447 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4451 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4455 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4459 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4467 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4471 if (r_trippy.integer)
4473 for (i = 0;i < numplanes;i++)
4480 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4484 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4488 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4492 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4496 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4500 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4504 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4508 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4516 //==================================================================================
4518 // LordHavoc: this stores temporary data used within the same frame
4520 typedef struct r_framedata_mem_s
4522 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4523 size_t size; // how much usable space
4524 size_t current; // how much space in use
4525 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4526 size_t wantedsize; // how much space was allocated
4527 unsigned char *data; // start of real data (16byte aligned)
4531 static r_framedata_mem_t *r_framedata_mem;
4533 void R_FrameData_Reset(void)
4535 while (r_framedata_mem)
4537 r_framedata_mem_t *next = r_framedata_mem->purge;
4538 Mem_Free(r_framedata_mem);
4539 r_framedata_mem = next;
4543 static void R_FrameData_Resize(qboolean mustgrow)
4546 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4547 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4548 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4550 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4551 newmem->wantedsize = wantedsize;
4552 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4553 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4554 newmem->current = 0;
4556 newmem->purge = r_framedata_mem;
4557 r_framedata_mem = newmem;
4561 void R_FrameData_NewFrame(void)
4563 R_FrameData_Resize(false);
4564 if (!r_framedata_mem)
4566 // if we ran out of space on the last frame, free the old memory now
4567 while (r_framedata_mem->purge)
4569 // repeatedly remove the second item in the list, leaving only head
4570 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4571 Mem_Free(r_framedata_mem->purge);
4572 r_framedata_mem->purge = next;
4574 // reset the current mem pointer
4575 r_framedata_mem->current = 0;
4576 r_framedata_mem->mark = 0;
4579 void *R_FrameData_Alloc(size_t size)
4584 // align to 16 byte boundary - the data pointer is already aligned, so we
4585 // only need to ensure the size of every allocation is also aligned
4586 size = (size + 15) & ~15;
4588 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4590 // emergency - we ran out of space, allocate more memory
4591 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4592 // this might not be a growing it, but we'll allocate another buffer every time
4593 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4594 R_FrameData_Resize(true);
4597 data = r_framedata_mem->data + r_framedata_mem->current;
4598 r_framedata_mem->current += size;
4600 // count the usage for stats
4601 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4602 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4604 return (void *)data;
4607 void *R_FrameData_Store(size_t size, void *data)
4609 void *d = R_FrameData_Alloc(size);
4611 memcpy(d, data, size);
4615 void R_FrameData_SetMark(void)
4617 if (!r_framedata_mem)
4619 r_framedata_mem->mark = r_framedata_mem->current;
4622 void R_FrameData_ReturnToMark(void)
4624 if (!r_framedata_mem)
4626 r_framedata_mem->current = r_framedata_mem->mark;
4629 //==================================================================================
4631 // avoid reusing the same buffer objects on consecutive buffers
4632 #define R_BUFFERDATA_CYCLE 2
4634 typedef struct r_bufferdata_buffer_s
4636 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4637 size_t size; // how much usable space
4638 size_t current; // how much space in use
4639 r_meshbuffer_t *buffer; // the buffer itself
4641 r_bufferdata_buffer_t;
4643 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4644 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4646 /// frees all dynamic buffers
4647 void R_BufferData_Reset(void)
4650 r_bufferdata_buffer_t **p, *mem;
4651 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4653 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4656 p = &r_bufferdata_buffer[r_bufferdata_cycle][type];
4662 R_Mesh_DestroyMeshBuffer(mem->buffer);
4669 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4670 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow)
4672 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4674 size = (size_t)(r_bufferdatasize[type].value * 1024*1024);
4675 size = bound(65536, size, 512*1024*1024);
4676 if (!mem || mem->size != size || mustgrow)
4678 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4681 if (type == R_BUFFERDATA_VERTEX)
4682 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4683 else if (type == R_BUFFERDATA_INDEX16)
4684 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4685 else if (type == R_BUFFERDATA_INDEX32)
4686 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4687 else if (type == R_BUFFERDATA_UNIFORM)
4688 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4689 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4690 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4694 void R_BufferData_NewFrame(void)
4697 r_bufferdata_buffer_t **p, *mem;
4698 // cycle to the next frame's buffers
4699 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4700 // if we ran out of space on the last time we used these buffers, free the old memory now
4701 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4703 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4705 R_BufferData_Resize(type, false);
4706 // free all but the head buffer, this is how we recycle obsolete
4707 // buffers after they are no longer in use
4708 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4714 R_Mesh_DestroyMeshBuffer(mem->buffer);
4717 // reset the current offset
4718 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4723 r_meshbuffer_t *R_BufferData_Store(size_t datasize, void *data, r_bufferdata_type_t type, int *returnbufferoffset, qboolean allowfail)
4725 r_bufferdata_buffer_t *mem;
4730 *returnbufferoffset = 0;
4732 // align size to a byte boundary appropriate for the buffer type, this
4733 // makes all allocations have aligned start offsets
4734 if (type == R_BUFFERDATA_UNIFORM)
4735 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4737 padsize = (datasize + 15) & ~15;
4739 while (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4741 // emergency - we ran out of space, allocate more memory
4742 newvalue = bound(0.25f, r_bufferdatasize[type].value * 2.0f, 256.0f);
4743 // if we're already at the limit, just fail (if allowfail is false we might run out of video ram)
4744 if (newvalue == r_bufferdatasize[type].value && allowfail)
4746 Cvar_SetValueQuick(&r_bufferdatasize[type], newvalue);
4747 R_BufferData_Resize(type, true);
4750 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4751 offset = mem->current;
4752 mem->current += padsize;
4754 // upload the data to the buffer at the chosen offset
4756 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4757 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4759 // count the usage for stats
4760 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4761 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4763 // return the buffer offset
4764 *returnbufferoffset = offset;
4769 //==================================================================================
4771 // LordHavoc: animcache originally written by Echon, rewritten since then
4774 * Animation cache prevents re-generating mesh data for an animated model
4775 * multiple times in one frame for lighting, shadowing, reflections, etc.
4778 void R_AnimCache_Free(void)
4782 void R_AnimCache_ClearCache(void)
4785 entity_render_t *ent;
4787 for (i = 0;i < r_refdef.scene.numentities;i++)
4789 ent = r_refdef.scene.entities[i];
4790 ent->animcache_vertex3f = NULL;
4791 ent->animcache_vertex3f_vertexbuffer = NULL;
4792 ent->animcache_vertex3f_bufferoffset = 0;
4793 ent->animcache_normal3f = NULL;
4794 ent->animcache_normal3f_vertexbuffer = NULL;
4795 ent->animcache_normal3f_bufferoffset = 0;
4796 ent->animcache_svector3f = NULL;
4797 ent->animcache_svector3f_vertexbuffer = NULL;
4798 ent->animcache_svector3f_bufferoffset = 0;
4799 ent->animcache_tvector3f = NULL;
4800 ent->animcache_tvector3f_vertexbuffer = NULL;
4801 ent->animcache_tvector3f_bufferoffset = 0;
4802 ent->animcache_vertexmesh = NULL;
4803 ent->animcache_vertexmesh_vertexbuffer = NULL;
4804 ent->animcache_vertexmesh_bufferoffset = 0;
4805 ent->animcache_skeletaltransform3x4 = NULL;
4806 ent->animcache_skeletaltransform3x4buffer = NULL;
4807 ent->animcache_skeletaltransform3x4offset = 0;
4808 ent->animcache_skeletaltransform3x4size = 0;
4812 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4816 // check if we need the meshbuffers
4817 if (!vid.useinterleavedarrays)
4820 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4821 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4822 // TODO: upload vertexbuffer?
4823 if (ent->animcache_vertexmesh)
4825 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4826 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4827 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4828 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4829 for (i = 0;i < numvertices;i++)
4830 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4831 if (ent->animcache_svector3f)
4832 for (i = 0;i < numvertices;i++)
4833 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4834 if (ent->animcache_tvector3f)
4835 for (i = 0;i < numvertices;i++)
4836 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4837 if (ent->animcache_normal3f)
4838 for (i = 0;i < numvertices;i++)
4839 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4843 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4845 dp_model_t *model = ent->model;
4848 // see if this ent is worth caching
4849 if (!model || !model->Draw || !model->AnimateVertices)
4851 // nothing to cache if it contains no animations and has no skeleton
4852 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4854 // see if it is already cached for gpuskeletal
4855 if (ent->animcache_skeletaltransform3x4)
4857 // see if it is already cached as a mesh
4858 if (ent->animcache_vertex3f)
4860 // check if we need to add normals or tangents
4861 if (ent->animcache_normal3f)
4862 wantnormals = false;
4863 if (ent->animcache_svector3f)
4864 wanttangents = false;
4865 if (!wantnormals && !wanttangents)
4869 // check which kind of cache we need to generate
4870 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4872 // cache the skeleton so the vertex shader can use it
4875 const skeleton_t *skeleton = ent->skeleton;
4876 const frameblend_t *frameblend = ent->frameblend;
4877 float *boneposerelative;
4879 static float bonepose[256][12];
4880 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4881 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4882 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4883 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4884 boneposerelative = ent->animcache_skeletaltransform3x4;
4885 if (skeleton && !skeleton->relativetransforms)
4887 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4890 for (i = 0;i < model->num_bones;i++)
4892 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4893 if (model->data_bones[i].parent >= 0)
4894 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4896 memcpy(bonepose[i], m, sizeof(m));
4898 // create a relative deformation matrix to describe displacement
4899 // from the base mesh, which is used by the actual weighting
4900 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4905 for (i = 0;i < model->num_bones;i++)
4907 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4908 float lerp = frameblend[0].lerp,
4909 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4910 rx = pose7s[3] * lerp,
4911 ry = pose7s[4] * lerp,
4912 rz = pose7s[5] * lerp,
4913 rw = pose7s[6] * lerp,
4914 dx = tx*rw + ty*rz - tz*ry,
4915 dy = -tx*rz + ty*rw + tz*rx,
4916 dz = tx*ry - ty*rx + tz*rw,
4917 dw = -tx*rx - ty*ry - tz*rz,
4918 scale, sx, sy, sz, sw;
4919 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4921 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4922 float lerp = frameblend[blends].lerp,
4923 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4924 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4925 if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4934 dx += tx*qw + ty*qz - tz*qy;
4935 dy += -tx*qz + ty*qw + tz*qx;
4936 dz += tx*qy - ty*qx + tz*qw;
4937 dw += -tx*qx - ty*qy - tz*qz;
4939 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4944 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4945 m[1] = 2*(sx*ry - sw*rz);
4946 m[2] = 2*(sx*rz + sw*ry);
4947 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4948 m[4] = 2*(sx*ry + sw*rz);
4949 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4950 m[6] = 2*(sy*rz - sw*rx);
4951 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4952 m[8] = 2*(sx*rz - sw*ry);
4953 m[9] = 2*(sy*rz + sw*rx);
4954 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4955 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4956 if (i == r_skeletal_debugbone.integer)
4957 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4958 m[3] *= r_skeletal_debugtranslatex.value;
4959 m[7] *= r_skeletal_debugtranslatey.value;
4960 m[11] *= r_skeletal_debugtranslatez.value;
4961 if (model->data_bones[i].parent >= 0)
4962 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4964 memcpy(bonepose[i], m, sizeof(m));
4965 // create a relative deformation matrix to describe displacement
4966 // from the base mesh, which is used by the actual weighting
4967 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4970 // note: this can fail if the buffer is at the grow limit
4971 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4972 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset, true);
4974 else if (ent->animcache_vertex3f)
4976 // mesh was already cached but we may need to add normals/tangents
4977 // (this only happens with multiple views, reflections, cameras, etc)
4978 if (wantnormals || wanttangents)
4980 numvertices = model->surfmesh.num_vertices;
4982 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4985 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4986 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4988 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4989 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4990 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4991 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4992 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4997 // generate mesh cache
4998 numvertices = model->surfmesh.num_vertices;
4999 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5001 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5004 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5005 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5007 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5008 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5009 if (wantnormals || wanttangents)
5011 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5012 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5013 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5015 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5016 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5017 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5022 void R_AnimCache_CacheVisibleEntities(void)
5025 qboolean wantnormals = true;
5026 qboolean wanttangents = !r_showsurfaces.integer;
5028 switch(vid.renderpath)
5030 case RENDERPATH_GL20:
5031 case RENDERPATH_D3D9:
5032 case RENDERPATH_D3D10:
5033 case RENDERPATH_D3D11:
5034 case RENDERPATH_GLES2:
5036 case RENDERPATH_GL11:
5037 case RENDERPATH_GL13:
5038 case RENDERPATH_GLES1:
5039 wanttangents = false;
5041 case RENDERPATH_SOFT:
5045 if (r_shownormals.integer)
5046 wanttangents = wantnormals = true;
5048 // TODO: thread this
5049 // NOTE: R_PrepareRTLights() also caches entities
5051 for (i = 0;i < r_refdef.scene.numentities;i++)
5052 if (r_refdef.viewcache.entityvisible[i])
5053 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5056 //==================================================================================
5058 extern cvar_t r_overheadsprites_pushback;
5060 static void R_View_UpdateEntityLighting (void)
5063 entity_render_t *ent;
5064 vec3_t tempdiffusenormal, avg;
5065 vec_t f, fa, fd, fdd;
5066 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5068 for (i = 0;i < r_refdef.scene.numentities;i++)
5070 ent = r_refdef.scene.entities[i];
5072 // skip unseen models
5073 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5077 if (ent->model && ent->model == cl.worldmodel)
5079 // TODO: use modellight for r_ambient settings on world?
5080 VectorSet(ent->modellight_ambient, 0, 0, 0);
5081 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5082 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5086 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5088 // aleady updated by CSQC
5089 // TODO: force modellight on BSP models in this case?
5090 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5094 // fetch the lighting from the worldmodel data
5095 VectorClear(ent->modellight_ambient);
5096 VectorClear(ent->modellight_diffuse);
5097 VectorClear(tempdiffusenormal);
5098 if (ent->flags & RENDER_LIGHT)
5101 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5103 // complete lightning for lit sprites
5104 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5105 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5107 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5108 org[2] = org[2] + r_overheadsprites_pushback.value;
5109 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5112 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5114 if(ent->flags & RENDER_EQUALIZE)
5116 // first fix up ambient lighting...
5117 if(r_equalize_entities_minambient.value > 0)
5119 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5122 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5123 if(fa < r_equalize_entities_minambient.value * fd)
5126 // fa'/fd' = minambient
5127 // fa'+0.25*fd' = fa+0.25*fd
5129 // fa' = fd' * minambient
5130 // fd'*(0.25+minambient) = fa+0.25*fd
5132 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5133 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5135 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5136 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
5137 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5138 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5143 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5145 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5146 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5150 // adjust brightness and saturation to target
5151 avg[0] = avg[1] = avg[2] = fa / f;
5152 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5153 avg[0] = avg[1] = avg[2] = fd / f;
5154 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5160 VectorSet(ent->modellight_ambient, 1, 1, 1);
5163 // move the light direction into modelspace coordinates for lighting code
5164 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5165 if(VectorLength2(ent->modellight_lightdir) == 0)
5166 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5167 VectorNormalize(ent->modellight_lightdir);
5171 #define MAX_LINEOFSIGHTTRACES 64
5173 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5176 vec3_t boxmins, boxmaxs;
5179 dp_model_t *model = r_refdef.scene.worldmodel;
5181 if (!model || !model->brush.TraceLineOfSight)
5184 // expand the box a little
5185 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5186 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5187 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5188 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5189 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5190 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5192 // return true if eye is inside enlarged box
5193 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5197 VectorCopy(eye, start);
5198 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5199 if (model->brush.TraceLineOfSight(model, start, end))
5202 // try various random positions
5203 for (i = 0;i < numsamples;i++)
5205 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5206 if (model->brush.TraceLineOfSight(model, start, end))
5214 static void R_View_UpdateEntityVisible (void)
5219 entity_render_t *ent;
5221 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5222 : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5223 : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL
5224 : RENDER_EXTERIORMODEL;
5225 if (!r_drawviewmodel.integer)
5226 renderimask |= RENDER_VIEWMODEL;
5227 if (!r_drawexteriormodel.integer)
5228 renderimask |= RENDER_EXTERIORMODEL;
5229 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5231 // worldmodel can check visibility
5232 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5233 for (i = 0;i < r_refdef.scene.numentities;i++)
5235 ent = r_refdef.scene.entities[i];
5236 if (!(ent->flags & renderimask))
5237 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)))
5238 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))
5239 r_refdef.viewcache.entityvisible[i] = true;
5244 // no worldmodel or it can't check visibility
5245 for (i = 0;i < r_refdef.scene.numentities;i++)
5247 ent = r_refdef.scene.entities[i];
5248 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));
5251 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5252 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
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->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5261 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5263 continue; // temp entities do pvs only
5264 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5265 ent->last_trace_visibility = realtime;
5266 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5267 r_refdef.viewcache.entityvisible[i] = 0;
5273 /// only used if skyrendermasked, and normally returns false
5274 static int R_DrawBrushModelsSky (void)
5277 entity_render_t *ent;
5280 for (i = 0;i < r_refdef.scene.numentities;i++)
5282 if (!r_refdef.viewcache.entityvisible[i])
5284 ent = r_refdef.scene.entities[i];
5285 if (!ent->model || !ent->model->DrawSky)
5287 ent->model->DrawSky(ent);
5293 static void R_DrawNoModel(entity_render_t *ent);
5294 static void R_DrawModels(void)
5297 entity_render_t *ent;
5299 for (i = 0;i < r_refdef.scene.numentities;i++)
5301 if (!r_refdef.viewcache.entityvisible[i])
5303 ent = r_refdef.scene.entities[i];
5304 r_refdef.stats[r_stat_entities]++;
5306 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5309 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5310 Con_Printf("R_DrawModels\n");
5311 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]);
5312 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);
5313 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);
5316 if (ent->model && ent->model->Draw != NULL)
5317 ent->model->Draw(ent);
5323 static void R_DrawModelsDepth(void)
5326 entity_render_t *ent;
5328 for (i = 0;i < r_refdef.scene.numentities;i++)
5330 if (!r_refdef.viewcache.entityvisible[i])
5332 ent = r_refdef.scene.entities[i];
5333 if (ent->model && ent->model->DrawDepth != NULL)
5334 ent->model->DrawDepth(ent);
5338 static void R_DrawModelsDebug(void)
5341 entity_render_t *ent;
5343 for (i = 0;i < r_refdef.scene.numentities;i++)
5345 if (!r_refdef.viewcache.entityvisible[i])
5347 ent = r_refdef.scene.entities[i];
5348 if (ent->model && ent->model->DrawDebug != NULL)
5349 ent->model->DrawDebug(ent);
5353 static void R_DrawModelsAddWaterPlanes(void)
5356 entity_render_t *ent;
5358 for (i = 0;i < r_refdef.scene.numentities;i++)
5360 if (!r_refdef.viewcache.entityvisible[i])
5362 ent = r_refdef.scene.entities[i];
5363 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5364 ent->model->DrawAddWaterPlanes(ent);
5368 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}};
5370 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5372 if (r_hdr_irisadaptation.integer)
5377 vec3_t diffusenormal;
5379 vec_t brightness = 0.0f;
5384 VectorCopy(r_refdef.view.forward, forward);
5385 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5387 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5388 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5389 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5390 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5391 d = DotProduct(forward, diffusenormal);
5392 brightness += VectorLength(ambient);
5394 brightness += d * VectorLength(diffuse);
5396 brightness *= 1.0f / c;
5397 brightness += 0.00001f; // make sure it's never zero
5398 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5399 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5400 current = r_hdr_irisadaptation_value.value;
5402 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5403 else if (current > goal)
5404 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5405 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5406 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5408 else if (r_hdr_irisadaptation_value.value != 1.0f)
5409 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5412 static void R_View_SetFrustum(const int *scissor)
5415 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5416 vec3_t forward, left, up, origin, v;
5420 // flipped x coordinates (because x points left here)
5421 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5422 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5424 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5425 switch(vid.renderpath)
5427 case RENDERPATH_D3D9:
5428 case RENDERPATH_D3D10:
5429 case RENDERPATH_D3D11:
5430 // non-flipped y coordinates
5431 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5432 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5434 case RENDERPATH_SOFT:
5435 case RENDERPATH_GL11:
5436 case RENDERPATH_GL13:
5437 case RENDERPATH_GL20:
5438 case RENDERPATH_GLES1:
5439 case RENDERPATH_GLES2:
5440 // non-flipped y coordinates
5441 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5442 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5447 // we can't trust r_refdef.view.forward and friends in reflected scenes
5448 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5451 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5452 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5453 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5454 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5455 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5456 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5457 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5458 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5459 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5460 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5461 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5462 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5466 zNear = r_refdef.nearclip;
5467 nudge = 1.0 - 1.0 / (1<<23);
5468 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5469 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5470 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5471 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5472 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5473 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5474 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5475 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5481 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5482 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5483 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5484 r_refdef.view.frustum[0].dist = m[15] - m[12];
5486 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5487 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5488 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5489 r_refdef.view.frustum[1].dist = m[15] + m[12];
5491 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5492 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5493 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5494 r_refdef.view.frustum[2].dist = m[15] - m[13];
5496 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5497 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5498 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5499 r_refdef.view.frustum[3].dist = m[15] + m[13];
5501 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5502 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5503 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5504 r_refdef.view.frustum[4].dist = m[15] - m[14];
5506 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5507 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5508 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5509 r_refdef.view.frustum[5].dist = m[15] + m[14];
5512 if (r_refdef.view.useperspective)
5514 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5515 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]);
5516 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]);
5517 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]);
5518 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]);
5520 // then the normals from the corners relative to origin
5521 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5522 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5523 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5524 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5526 // in a NORMAL view, forward cross left == up
5527 // in a REFLECTED view, forward cross left == down
5528 // so our cross products above need to be adjusted for a left handed coordinate system
5529 CrossProduct(forward, left, v);
5530 if(DotProduct(v, up) < 0)
5532 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5533 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5534 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5535 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5538 // Leaving those out was a mistake, those were in the old code, and they
5539 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5540 // I couldn't reproduce it after adding those normalizations. --blub
5541 VectorNormalize(r_refdef.view.frustum[0].normal);
5542 VectorNormalize(r_refdef.view.frustum[1].normal);
5543 VectorNormalize(r_refdef.view.frustum[2].normal);
5544 VectorNormalize(r_refdef.view.frustum[3].normal);
5546 // make the corners absolute
5547 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5548 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5549 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5550 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5553 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5555 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5556 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5557 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5558 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5559 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5563 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5564 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5565 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5566 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5567 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5568 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5569 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5570 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5571 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5572 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5574 r_refdef.view.numfrustumplanes = 5;
5576 if (r_refdef.view.useclipplane)
5578 r_refdef.view.numfrustumplanes = 6;
5579 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5582 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5583 PlaneClassify(r_refdef.view.frustum + i);
5585 // LordHavoc: note to all quake engine coders, Quake had a special case
5586 // for 90 degrees which assumed a square view (wrong), so I removed it,
5587 // Quake2 has it disabled as well.
5589 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5590 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5591 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5592 //PlaneClassify(&frustum[0]);
5594 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5595 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5596 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5597 //PlaneClassify(&frustum[1]);
5599 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5600 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5601 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5602 //PlaneClassify(&frustum[2]);
5604 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5605 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5606 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5607 //PlaneClassify(&frustum[3]);
5610 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5611 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5612 //PlaneClassify(&frustum[4]);
5615 static void R_View_UpdateWithScissor(const int *myscissor)
5617 R_Main_ResizeViewCache();
5618 R_View_SetFrustum(myscissor);
5619 R_View_WorldVisibility(r_refdef.view.useclipplane);
5620 R_View_UpdateEntityVisible();
5621 R_View_UpdateEntityLighting();
5624 static void R_View_Update(void)
5626 R_Main_ResizeViewCache();
5627 R_View_SetFrustum(NULL);
5628 R_View_WorldVisibility(r_refdef.view.useclipplane);
5629 R_View_UpdateEntityVisible();
5630 R_View_UpdateEntityLighting();
5633 float viewscalefpsadjusted = 1.0f;
5635 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5637 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5638 scale = bound(0.03125f, scale, 1.0f);
5639 *outwidth = (int)ceil(width * scale);
5640 *outheight = (int)ceil(height * scale);
5643 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5645 const float *customclipplane = NULL;
5647 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5648 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5650 // LordHavoc: couldn't figure out how to make this approach the
5651 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5652 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5653 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5654 dist = r_refdef.view.clipplane.dist;
5655 plane[0] = r_refdef.view.clipplane.normal[0];
5656 plane[1] = r_refdef.view.clipplane.normal[1];
5657 plane[2] = r_refdef.view.clipplane.normal[2];
5659 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5662 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5663 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5665 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5666 if (!r_refdef.view.useperspective)
5667 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);
5668 else if (vid.stencil && r_useinfinitefarclip.integer)
5669 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);
5671 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);
5672 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5673 R_SetViewport(&r_refdef.view.viewport);
5674 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5676 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5677 float screenplane[4];
5678 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5679 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5680 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5681 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5682 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5686 void R_EntityMatrix(const matrix4x4_t *matrix)
5688 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5690 gl_modelmatrixchanged = false;
5691 gl_modelmatrix = *matrix;
5692 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5693 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5694 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5695 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5697 switch(vid.renderpath)
5699 case RENDERPATH_D3D9:
5701 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5702 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5705 case RENDERPATH_D3D10:
5706 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5708 case RENDERPATH_D3D11:
5709 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5711 case RENDERPATH_GL11:
5712 case RENDERPATH_GL13:
5713 case RENDERPATH_GLES1:
5714 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5716 case RENDERPATH_SOFT:
5717 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5718 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5720 case RENDERPATH_GL20:
5721 case RENDERPATH_GLES2:
5722 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5723 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5729 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5731 r_viewport_t viewport;
5735 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5736 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);
5737 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5738 R_SetViewport(&viewport);
5739 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5740 GL_Color(1, 1, 1, 1);
5741 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5742 GL_BlendFunc(GL_ONE, GL_ZERO);
5743 GL_ScissorTest(false);
5744 GL_DepthMask(false);
5745 GL_DepthRange(0, 1);
5746 GL_DepthTest(false);
5747 GL_DepthFunc(GL_LEQUAL);
5748 R_EntityMatrix(&identitymatrix);
5749 R_Mesh_ResetTextureState();
5750 GL_PolygonOffset(0, 0);
5751 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5752 switch(vid.renderpath)
5754 case RENDERPATH_GL11:
5755 case RENDERPATH_GL13:
5756 case RENDERPATH_GL20:
5757 case RENDERPATH_GLES1:
5758 case RENDERPATH_GLES2:
5759 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5761 case RENDERPATH_D3D9:
5762 case RENDERPATH_D3D10:
5763 case RENDERPATH_D3D11:
5764 case RENDERPATH_SOFT:
5767 GL_CullFace(GL_NONE);
5772 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5776 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5779 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5783 R_SetupView(true, fbo, depthtexture, colortexture);
5784 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5785 GL_Color(1, 1, 1, 1);
5786 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5787 GL_BlendFunc(GL_ONE, GL_ZERO);
5788 GL_ScissorTest(true);
5790 GL_DepthRange(0, 1);
5792 GL_DepthFunc(GL_LEQUAL);
5793 R_EntityMatrix(&identitymatrix);
5794 R_Mesh_ResetTextureState();
5795 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5796 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5797 switch(vid.renderpath)
5799 case RENDERPATH_GL11:
5800 case RENDERPATH_GL13:
5801 case RENDERPATH_GL20:
5802 case RENDERPATH_GLES1:
5803 case RENDERPATH_GLES2:
5804 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5806 case RENDERPATH_D3D9:
5807 case RENDERPATH_D3D10:
5808 case RENDERPATH_D3D11:
5809 case RENDERPATH_SOFT:
5812 GL_CullFace(r_refdef.view.cullface_back);
5817 R_RenderView_UpdateViewVectors
5820 void R_RenderView_UpdateViewVectors(void)
5822 // break apart the view matrix into vectors for various purposes
5823 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5824 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5825 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5826 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5827 // make an inverted copy of the view matrix for tracking sprites
5828 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5831 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5832 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5834 static void R_Water_StartFrame(void)
5837 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5838 r_waterstate_waterplane_t *p;
5839 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;
5841 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5844 switch(vid.renderpath)
5846 case RENDERPATH_GL20:
5847 case RENDERPATH_D3D9:
5848 case RENDERPATH_D3D10:
5849 case RENDERPATH_D3D11:
5850 case RENDERPATH_SOFT:
5851 case RENDERPATH_GLES2:
5853 case RENDERPATH_GL11:
5854 case RENDERPATH_GL13:
5855 case RENDERPATH_GLES1:
5859 // set waterwidth and waterheight to the water resolution that will be
5860 // used (often less than the screen resolution for faster rendering)
5861 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5863 // calculate desired texture sizes
5864 // can't use water if the card does not support the texture size
5865 if (!r_water.integer || r_showsurfaces.integer)
5866 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5867 else if (vid.support.arb_texture_non_power_of_two)
5869 texturewidth = waterwidth;
5870 textureheight = waterheight;
5871 camerawidth = waterwidth;
5872 cameraheight = waterheight;
5876 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5877 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5878 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5879 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5882 // allocate textures as needed
5883 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))
5885 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5886 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5888 if (p->texture_refraction)
5889 R_FreeTexture(p->texture_refraction);
5890 p->texture_refraction = NULL;
5891 if (p->fbo_refraction)
5892 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5893 p->fbo_refraction = 0;
5894 if (p->texture_reflection)
5895 R_FreeTexture(p->texture_reflection);
5896 p->texture_reflection = NULL;
5897 if (p->fbo_reflection)
5898 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5899 p->fbo_reflection = 0;
5900 if (p->texture_camera)
5901 R_FreeTexture(p->texture_camera);
5902 p->texture_camera = NULL;
5904 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5907 memset(&r_fb.water, 0, sizeof(r_fb.water));
5908 r_fb.water.texturewidth = texturewidth;
5909 r_fb.water.textureheight = textureheight;
5910 r_fb.water.camerawidth = camerawidth;
5911 r_fb.water.cameraheight = cameraheight;
5914 if (r_fb.water.texturewidth)
5916 int scaledwidth, scaledheight;
5918 r_fb.water.enabled = true;
5920 // water resolution is usually reduced
5921 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5922 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5923 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5925 // set up variables that will be used in shader setup
5926 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5927 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5928 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5929 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5932 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5933 r_fb.water.numwaterplanes = 0;
5936 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5938 int planeindex, bestplaneindex, vertexindex;
5939 vec3_t mins, maxs, normal, center, v, n;
5940 vec_t planescore, bestplanescore;
5942 r_waterstate_waterplane_t *p;
5943 texture_t *t = R_GetCurrentTexture(surface->texture);
5945 rsurface.texture = t;
5946 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5947 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5948 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5950 // average the vertex normals, find the surface bounds (after deformvertexes)
5951 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5952 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5953 VectorCopy(n, normal);
5954 VectorCopy(v, mins);
5955 VectorCopy(v, maxs);
5956 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5958 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5959 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5960 VectorAdd(normal, n, normal);
5961 mins[0] = min(mins[0], v[0]);
5962 mins[1] = min(mins[1], v[1]);
5963 mins[2] = min(mins[2], v[2]);
5964 maxs[0] = max(maxs[0], v[0]);
5965 maxs[1] = max(maxs[1], v[1]);
5966 maxs[2] = max(maxs[2], v[2]);
5968 VectorNormalize(normal);
5969 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5971 VectorCopy(normal, plane.normal);
5972 VectorNormalize(plane.normal);
5973 plane.dist = DotProduct(center, plane.normal);
5974 PlaneClassify(&plane);
5975 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5977 // skip backfaces (except if nocullface is set)
5978 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5980 VectorNegate(plane.normal, plane.normal);
5982 PlaneClassify(&plane);
5986 // find a matching plane if there is one
5987 bestplaneindex = -1;
5988 bestplanescore = 1048576.0f;
5989 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5991 if(p->camera_entity == t->camera_entity)
5993 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5994 if (bestplaneindex < 0 || bestplanescore > planescore)
5996 bestplaneindex = planeindex;
5997 bestplanescore = planescore;
6001 planeindex = bestplaneindex;
6002 p = r_fb.water.waterplanes + planeindex;
6004 // if this surface does not fit any known plane rendered this frame, add one
6005 if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6007 // store the new plane
6008 planeindex = r_fb.water.numwaterplanes++;
6009 p = r_fb.water.waterplanes + planeindex;
6011 // clear materialflags and pvs
6012 p->materialflags = 0;
6013 p->pvsvalid = false;
6014 p->camera_entity = t->camera_entity;
6015 VectorCopy(mins, p->mins);
6016 VectorCopy(maxs, p->maxs);
6020 // merge mins/maxs when we're adding this surface to the plane
6021 p->mins[0] = min(p->mins[0], mins[0]);
6022 p->mins[1] = min(p->mins[1], mins[1]);
6023 p->mins[2] = min(p->mins[2], mins[2]);
6024 p->maxs[0] = max(p->maxs[0], maxs[0]);
6025 p->maxs[1] = max(p->maxs[1], maxs[1]);
6026 p->maxs[2] = max(p->maxs[2], maxs[2]);
6028 // merge this surface's materialflags into the waterplane
6029 p->materialflags |= t->currentmaterialflags;
6030 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6032 // merge this surface's PVS into the waterplane
6033 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6034 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6036 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6042 extern cvar_t r_drawparticles;
6043 extern cvar_t r_drawdecals;
6045 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6048 r_refdef_view_t originalview;
6049 r_refdef_view_t myview;
6050 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;
6051 r_waterstate_waterplane_t *p;
6053 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;
6056 originalview = r_refdef.view;
6058 // lowquality hack, temporarily shut down some cvars and restore afterwards
6059 qualityreduction = r_water_lowquality.integer;
6060 if (qualityreduction > 0)
6062 if (qualityreduction >= 1)
6064 old_r_shadows = r_shadows.integer;
6065 old_r_worldrtlight = r_shadow_realtime_world.integer;
6066 old_r_dlight = r_shadow_realtime_dlight.integer;
6067 Cvar_SetValueQuick(&r_shadows, 0);
6068 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6069 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6071 if (qualityreduction >= 2)
6073 old_r_dynamic = r_dynamic.integer;
6074 old_r_particles = r_drawparticles.integer;
6075 old_r_decals = r_drawdecals.integer;
6076 Cvar_SetValueQuick(&r_dynamic, 0);
6077 Cvar_SetValueQuick(&r_drawparticles, 0);
6078 Cvar_SetValueQuick(&r_drawdecals, 0);
6082 // make sure enough textures are allocated
6083 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6085 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6087 if (!p->texture_refraction)
6088 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);
6089 if (!p->texture_refraction)
6093 if (r_fb.water.depthtexture == NULL)
6094 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6095 if (p->fbo_refraction == 0)
6096 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6099 else if (p->materialflags & MATERIALFLAG_CAMERA)
6101 if (!p->texture_camera)
6102 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);
6103 if (!p->texture_camera)
6107 if (r_fb.water.depthtexture == NULL)
6108 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6109 if (p->fbo_camera == 0)
6110 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6114 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6116 if (!p->texture_reflection)
6117 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);
6118 if (!p->texture_reflection)
6122 if (r_fb.water.depthtexture == NULL)
6123 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6124 if (p->fbo_reflection == 0)
6125 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6131 r_refdef.view = originalview;
6132 r_refdef.view.showdebug = false;
6133 r_refdef.view.width = r_fb.water.waterwidth;
6134 r_refdef.view.height = r_fb.water.waterheight;
6135 r_refdef.view.useclipplane = true;
6136 myview = r_refdef.view;
6137 r_fb.water.renderingscene = true;
6138 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6140 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6142 r_refdef.view = myview;
6143 if(r_water_scissormode.integer)
6145 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6146 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6147 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6150 // render reflected scene and copy into texture
6151 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6152 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6153 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6154 r_refdef.view.clipplane = p->plane;
6155 // reverse the cullface settings for this render
6156 r_refdef.view.cullface_front = GL_FRONT;
6157 r_refdef.view.cullface_back = GL_BACK;
6158 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6160 r_refdef.view.usecustompvs = true;
6162 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6164 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6167 r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6168 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6169 R_ClearScreen(r_refdef.fogenabled);
6170 if(r_water_scissormode.integer & 2)
6171 R_View_UpdateWithScissor(myscissor);
6174 R_AnimCache_CacheVisibleEntities();
6175 if(r_water_scissormode.integer & 1)
6176 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6177 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6179 if (!p->fbo_reflection)
6180 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);
6181 r_fb.water.hideplayer = false;
6184 // render the normal view scene and copy into texture
6185 // (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)
6186 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6188 r_refdef.view = myview;
6189 if(r_water_scissormode.integer)
6191 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6192 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6193 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6196 r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6198 r_refdef.view.clipplane = p->plane;
6199 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6200 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6202 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6204 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6205 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6206 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6207 R_RenderView_UpdateViewVectors();
6208 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6210 r_refdef.view.usecustompvs = true;
6211 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);
6215 PlaneClassify(&r_refdef.view.clipplane);
6217 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6218 R_ClearScreen(r_refdef.fogenabled);
6219 if(r_water_scissormode.integer & 2)
6220 R_View_UpdateWithScissor(myscissor);
6223 R_AnimCache_CacheVisibleEntities();
6224 if(r_water_scissormode.integer & 1)
6225 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6226 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6228 if (!p->fbo_refraction)
6229 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);
6230 r_fb.water.hideplayer = false;
6232 else if (p->materialflags & MATERIALFLAG_CAMERA)
6234 r_refdef.view = myview;
6236 r_refdef.view.clipplane = p->plane;
6237 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6238 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6240 r_refdef.view.width = r_fb.water.camerawidth;
6241 r_refdef.view.height = r_fb.water.cameraheight;
6242 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6243 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6244 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6245 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6247 if(p->camera_entity)
6249 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6250 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6253 // note: all of the view is used for displaying... so
6254 // there is no use in scissoring
6256 // reverse the cullface settings for this render
6257 r_refdef.view.cullface_front = GL_FRONT;
6258 r_refdef.view.cullface_back = GL_BACK;
6259 // also reverse the view matrix
6260 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
6261 R_RenderView_UpdateViewVectors();
6262 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6264 r_refdef.view.usecustompvs = true;
6265 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);
6268 // camera needs no clipplane
6269 r_refdef.view.useclipplane = false;
6271 PlaneClassify(&r_refdef.view.clipplane);
6273 r_fb.water.hideplayer = false;
6275 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6276 R_ClearScreen(r_refdef.fogenabled);
6278 R_AnimCache_CacheVisibleEntities();
6279 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6282 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);
6283 r_fb.water.hideplayer = false;
6287 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6288 r_fb.water.renderingscene = false;
6289 r_refdef.view = originalview;
6290 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6291 if (!r_fb.water.depthtexture)
6292 R_ClearScreen(r_refdef.fogenabled);
6294 R_AnimCache_CacheVisibleEntities();
6297 r_refdef.view = originalview;
6298 r_fb.water.renderingscene = false;
6299 Cvar_SetValueQuick(&r_water, 0);
6300 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6302 // lowquality hack, restore cvars
6303 if (qualityreduction > 0)
6305 if (qualityreduction >= 1)
6307 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6308 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6309 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6311 if (qualityreduction >= 2)
6313 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6314 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6315 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6320 static void R_Bloom_StartFrame(void)
6323 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6324 int viewwidth, viewheight;
6325 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6326 textype_t textype = TEXTYPE_COLORBUFFER;
6328 switch (vid.renderpath)
6330 case RENDERPATH_GL20:
6331 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6332 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6334 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6335 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6338 case RENDERPATH_GL11:
6339 case RENDERPATH_GL13:
6340 case RENDERPATH_GLES1:
6341 case RENDERPATH_GLES2:
6342 case RENDERPATH_D3D9:
6343 case RENDERPATH_D3D10:
6344 case RENDERPATH_D3D11:
6345 r_fb.usedepthtextures = false;
6347 case RENDERPATH_SOFT:
6348 r_fb.usedepthtextures = true;
6352 if (r_viewscale_fpsscaling.integer)
6354 double actualframetime;
6355 double targetframetime;
6357 actualframetime = r_refdef.lastdrawscreentime;
6358 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6359 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6360 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6361 if (r_viewscale_fpsscaling_stepsize.value > 0)
6362 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6363 viewscalefpsadjusted += adjust;
6364 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6367 viewscalefpsadjusted = 1.0f;
6369 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6371 switch(vid.renderpath)
6373 case RENDERPATH_GL20:
6374 case RENDERPATH_D3D9:
6375 case RENDERPATH_D3D10:
6376 case RENDERPATH_D3D11:
6377 case RENDERPATH_SOFT:
6378 case RENDERPATH_GLES2:
6380 case RENDERPATH_GL11:
6381 case RENDERPATH_GL13:
6382 case RENDERPATH_GLES1:
6386 // set bloomwidth and bloomheight to the bloom resolution that will be
6387 // used (often less than the screen resolution for faster rendering)
6388 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6389 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6390 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6391 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6392 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6394 // calculate desired texture sizes
6395 if (vid.support.arb_texture_non_power_of_two)
6397 screentexturewidth = vid.width;
6398 screentextureheight = vid.height;
6399 bloomtexturewidth = r_fb.bloomwidth;
6400 bloomtextureheight = r_fb.bloomheight;
6404 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6405 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6406 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6407 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6410 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))
6412 Cvar_SetValueQuick(&r_bloom, 0);
6413 Cvar_SetValueQuick(&r_motionblur, 0);
6414 Cvar_SetValueQuick(&r_damageblur, 0);
6417 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6419 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6421 && r_viewscale.value == 1.0f
6422 && !r_viewscale_fpsscaling.integer)
6423 screentexturewidth = screentextureheight = 0;
6424 if (!r_bloom.integer)
6425 bloomtexturewidth = bloomtextureheight = 0;
6427 // allocate textures as needed
6428 if (r_fb.screentexturewidth != screentexturewidth
6429 || r_fb.screentextureheight != screentextureheight
6430 || r_fb.bloomtexturewidth != bloomtexturewidth
6431 || r_fb.bloomtextureheight != bloomtextureheight
6432 || r_fb.textype != textype
6433 || useviewfbo != (r_fb.fbo != 0))
6435 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6437 if (r_fb.bloomtexture[i])
6438 R_FreeTexture(r_fb.bloomtexture[i]);
6439 r_fb.bloomtexture[i] = NULL;
6441 if (r_fb.bloomfbo[i])
6442 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6443 r_fb.bloomfbo[i] = 0;
6447 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6450 if (r_fb.colortexture)
6451 R_FreeTexture(r_fb.colortexture);
6452 r_fb.colortexture = NULL;
6454 if (r_fb.depthtexture)
6455 R_FreeTexture(r_fb.depthtexture);
6456 r_fb.depthtexture = NULL;
6458 if (r_fb.ghosttexture)
6459 R_FreeTexture(r_fb.ghosttexture);
6460 r_fb.ghosttexture = NULL;
6462 r_fb.screentexturewidth = screentexturewidth;
6463 r_fb.screentextureheight = screentextureheight;
6464 r_fb.bloomtexturewidth = bloomtexturewidth;
6465 r_fb.bloomtextureheight = bloomtextureheight;
6466 r_fb.textype = textype;
6468 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6470 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6471 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);
6472 r_fb.ghosttexture_valid = false;
6473 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);
6476 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6477 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6478 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6482 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6484 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6486 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);
6488 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6493 // bloom texture is a different resolution
6494 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6495 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6496 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6497 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6498 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6500 // set up a texcoord array for the full resolution screen image
6501 // (we have to keep this around to copy back during final render)
6502 r_fb.screentexcoord2f[0] = 0;
6503 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6504 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6505 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6506 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6507 r_fb.screentexcoord2f[5] = 0;
6508 r_fb.screentexcoord2f[6] = 0;
6509 r_fb.screentexcoord2f[7] = 0;
6513 for (i = 1;i < 8;i += 2)
6515 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6519 // set up a texcoord array for the reduced resolution bloom image
6520 // (which will be additive blended over the screen image)
6521 r_fb.bloomtexcoord2f[0] = 0;
6522 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6523 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6524 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6525 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6526 r_fb.bloomtexcoord2f[5] = 0;
6527 r_fb.bloomtexcoord2f[6] = 0;
6528 r_fb.bloomtexcoord2f[7] = 0;
6530 switch(vid.renderpath)
6532 case RENDERPATH_GL11:
6533 case RENDERPATH_GL13:
6534 case RENDERPATH_GL20:
6535 case RENDERPATH_SOFT:
6536 case RENDERPATH_GLES1:
6537 case RENDERPATH_GLES2:
6539 case RENDERPATH_D3D9:
6540 case RENDERPATH_D3D10:
6541 case RENDERPATH_D3D11:
6542 for (i = 0;i < 4;i++)
6544 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6545 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6546 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6547 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6552 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6555 r_refdef.view.clear = true;
6558 static void R_Bloom_MakeTexture(void)
6561 float xoffset, yoffset, r, brighten;
6563 float colorscale = r_bloom_colorscale.value;
6565 r_refdef.stats[r_stat_bloom]++;
6568 // this copy is unnecessary since it happens in R_BlendView already
6571 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);
6572 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6576 // scale down screen texture to the bloom texture size
6578 r_fb.bloomindex = 0;
6579 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6580 R_SetViewport(&r_fb.bloomviewport);
6581 GL_DepthTest(false);
6582 GL_BlendFunc(GL_ONE, GL_ZERO);
6583 GL_Color(colorscale, colorscale, colorscale, 1);
6584 // 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...
6585 switch(vid.renderpath)
6587 case RENDERPATH_GL11:
6588 case RENDERPATH_GL13:
6589 case RENDERPATH_GL20:
6590 case RENDERPATH_GLES1:
6591 case RENDERPATH_GLES2:
6592 case RENDERPATH_SOFT:
6593 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6595 case RENDERPATH_D3D9:
6596 case RENDERPATH_D3D10:
6597 case RENDERPATH_D3D11:
6598 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6601 // TODO: do boxfilter scale-down in shader?
6602 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6603 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6604 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6606 // we now have a properly scaled bloom image
6607 if (!r_fb.bloomfbo[r_fb.bloomindex])
6609 // copy it into the bloom texture
6610 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);
6611 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6614 // multiply bloom image by itself as many times as desired
6615 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6617 intex = r_fb.bloomtexture[r_fb.bloomindex];
6618 r_fb.bloomindex ^= 1;
6619 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6621 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6622 if (!r_fb.bloomfbo[r_fb.bloomindex])
6624 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6625 GL_Color(r,r,r,1); // apply fix factor
6630 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6631 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6632 GL_Color(1,1,1,1); // no fix factor supported here
6634 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6635 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6636 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6637 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6639 if (!r_fb.bloomfbo[r_fb.bloomindex])
6641 // copy the darkened image to a texture
6642 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);
6643 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6647 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6648 brighten = r_bloom_brighten.value;
6649 brighten = sqrt(brighten);
6651 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6653 for (dir = 0;dir < 2;dir++)
6655 intex = r_fb.bloomtexture[r_fb.bloomindex];
6656 r_fb.bloomindex ^= 1;
6657 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6658 // blend on at multiple vertical offsets to achieve a vertical blur
6659 // TODO: do offset blends using GLSL
6660 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6661 GL_BlendFunc(GL_ONE, GL_ZERO);
6662 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6663 for (x = -range;x <= range;x++)
6665 if (!dir){xoffset = 0;yoffset = x;}
6666 else {xoffset = x;yoffset = 0;}
6667 xoffset /= (float)r_fb.bloomtexturewidth;
6668 yoffset /= (float)r_fb.bloomtextureheight;
6669 // compute a texcoord array with the specified x and y offset
6670 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6671 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6672 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6673 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6674 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6675 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6676 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6677 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6678 // this r value looks like a 'dot' particle, fading sharply to
6679 // black at the edges
6680 // (probably not realistic but looks good enough)
6681 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6682 //r = brighten/(range*2+1);
6683 r = brighten / (range * 2 + 1);
6685 r *= (1 - x*x/(float)(range*range));
6686 GL_Color(r, r, r, 1);
6687 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6688 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6689 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6690 GL_BlendFunc(GL_ONE, GL_ONE);
6693 if (!r_fb.bloomfbo[r_fb.bloomindex])
6695 // copy the vertically or horizontally blurred bloom view to a texture
6696 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);
6697 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6702 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6704 unsigned int permutation;
6705 float uservecs[4][4];
6707 R_EntityMatrix(&identitymatrix);
6709 switch (vid.renderpath)
6711 case RENDERPATH_GL20:
6712 case RENDERPATH_D3D9:
6713 case RENDERPATH_D3D10:
6714 case RENDERPATH_D3D11:
6715 case RENDERPATH_SOFT:
6716 case RENDERPATH_GLES2:
6718 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6719 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6720 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6721 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6722 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6724 if (r_fb.colortexture)
6728 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);
6729 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6732 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6734 // declare variables
6735 float blur_factor, blur_mouseaccel, blur_velocity;
6736 static float blur_average;
6737 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6739 // set a goal for the factoring
6740 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6741 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6742 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6743 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6744 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6745 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6747 // from the goal, pick an averaged value between goal and last value
6748 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6749 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6751 // enforce minimum amount of blur
6752 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6754 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6756 // calculate values into a standard alpha
6757 cl.motionbluralpha = 1 - exp(-
6759 (r_motionblur.value * blur_factor / 80)
6761 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6764 max(0.0001, cl.time - cl.oldtime) // fps independent
6767 // randomization for the blur value to combat persistent ghosting
6768 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6769 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6772 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6773 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6775 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6776 GL_Color(1, 1, 1, cl.motionbluralpha);
6777 switch(vid.renderpath)
6779 case RENDERPATH_GL11:
6780 case RENDERPATH_GL13:
6781 case RENDERPATH_GL20:
6782 case RENDERPATH_GLES1:
6783 case RENDERPATH_GLES2:
6784 case RENDERPATH_SOFT:
6785 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6787 case RENDERPATH_D3D9:
6788 case RENDERPATH_D3D10:
6789 case RENDERPATH_D3D11:
6790 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6793 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6794 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6795 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6798 // updates old view angles for next pass
6799 VectorCopy(cl.viewangles, blur_oldangles);
6801 // copy view into the ghost texture
6802 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);
6803 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6804 r_fb.ghosttexture_valid = true;
6809 // no r_fb.colortexture means we're rendering to the real fb
6810 // we may still have to do view tint...
6811 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6813 // apply a color tint to the whole view
6814 R_ResetViewRendering2D(0, NULL, NULL);
6815 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6816 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6817 R_SetupShader_Generic_NoTexture(false, true);
6818 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6819 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6821 break; // no screen processing, no bloom, skip it
6824 if (r_fb.bloomtexture[0])
6826 // make the bloom texture
6827 R_Bloom_MakeTexture();
6830 #if _MSC_VER >= 1400
6831 #define sscanf sscanf_s
6833 memset(uservecs, 0, sizeof(uservecs));
6834 if (r_glsl_postprocess_uservec1_enable.integer)
6835 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6836 if (r_glsl_postprocess_uservec2_enable.integer)
6837 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6838 if (r_glsl_postprocess_uservec3_enable.integer)
6839 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6840 if (r_glsl_postprocess_uservec4_enable.integer)
6841 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6843 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6844 GL_Color(1, 1, 1, 1);
6845 GL_BlendFunc(GL_ONE, GL_ZERO);
6847 switch(vid.renderpath)
6849 case RENDERPATH_GL20:
6850 case RENDERPATH_GLES2:
6851 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6852 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6853 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6854 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6855 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6856 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]);
6857 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6858 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]);
6859 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]);
6860 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]);
6861 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]);
6862 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6863 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6864 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);
6866 case RENDERPATH_D3D9:
6868 // 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...
6869 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6870 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6871 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6872 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6873 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6874 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6875 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6876 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6877 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6878 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6879 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6880 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6881 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6882 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6885 case RENDERPATH_D3D10:
6886 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6888 case RENDERPATH_D3D11:
6889 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6891 case RENDERPATH_SOFT:
6892 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6893 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6894 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6895 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6896 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6897 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6898 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6899 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6900 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6901 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6902 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6903 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6904 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6905 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6910 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6911 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6913 case RENDERPATH_GL11:
6914 case RENDERPATH_GL13:
6915 case RENDERPATH_GLES1:
6916 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6918 // apply a color tint to the whole view
6919 R_ResetViewRendering2D(0, NULL, NULL);
6920 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6921 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6922 R_SetupShader_Generic_NoTexture(false, true);
6923 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6924 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6930 matrix4x4_t r_waterscrollmatrix;
6932 void R_UpdateFog(void)
6935 if (gamemode == GAME_NEHAHRA)
6937 if (gl_fogenable.integer)
6939 r_refdef.oldgl_fogenable = true;
6940 r_refdef.fog_density = gl_fogdensity.value;
6941 r_refdef.fog_red = gl_fogred.value;
6942 r_refdef.fog_green = gl_foggreen.value;
6943 r_refdef.fog_blue = gl_fogblue.value;
6944 r_refdef.fog_alpha = 1;
6945 r_refdef.fog_start = 0;
6946 r_refdef.fog_end = gl_skyclip.value;
6947 r_refdef.fog_height = 1<<30;
6948 r_refdef.fog_fadedepth = 128;
6950 else if (r_refdef.oldgl_fogenable)
6952 r_refdef.oldgl_fogenable = false;
6953 r_refdef.fog_density = 0;
6954 r_refdef.fog_red = 0;
6955 r_refdef.fog_green = 0;
6956 r_refdef.fog_blue = 0;
6957 r_refdef.fog_alpha = 0;
6958 r_refdef.fog_start = 0;
6959 r_refdef.fog_end = 0;
6960 r_refdef.fog_height = 1<<30;
6961 r_refdef.fog_fadedepth = 128;
6966 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6967 r_refdef.fog_start = max(0, r_refdef.fog_start);
6968 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6970 if (r_refdef.fog_density && r_drawfog.integer)
6972 r_refdef.fogenabled = true;
6973 // this is the point where the fog reaches 0.9986 alpha, which we
6974 // consider a good enough cutoff point for the texture
6975 // (0.9986 * 256 == 255.6)
6976 if (r_fog_exp2.integer)
6977 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6979 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6980 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6981 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6982 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6983 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6984 R_BuildFogHeightTexture();
6985 // fog color was already set
6986 // update the fog texture
6987 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)
6988 R_BuildFogTexture();
6989 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6990 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6993 r_refdef.fogenabled = false;
6996 if (r_refdef.fog_density)
6998 r_refdef.fogcolor[0] = r_refdef.fog_red;
6999 r_refdef.fogcolor[1] = r_refdef.fog_green;
7000 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7002 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7003 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7004 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7005 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7009 VectorCopy(r_refdef.fogcolor, fogvec);
7010 // color.rgb *= ContrastBoost * SceneBrightness;
7011 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7012 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7013 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7014 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7019 void R_UpdateVariables(void)
7023 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7025 r_refdef.farclip = r_farclip_base.value;
7026 if (r_refdef.scene.worldmodel)
7027 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7028 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7030 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7031 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7032 r_refdef.polygonfactor = 0;
7033 r_refdef.polygonoffset = 0;
7034 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7035 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7037 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7038 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7039 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7040 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7041 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7042 if (FAKELIGHT_ENABLED)
7044 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7046 else if (r_refdef.scene.worldmodel)
7048 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7050 if (r_showsurfaces.integer)
7052 r_refdef.scene.rtworld = false;
7053 r_refdef.scene.rtworldshadows = false;
7054 r_refdef.scene.rtdlight = false;
7055 r_refdef.scene.rtdlightshadows = false;
7056 r_refdef.lightmapintensity = 0;
7059 r_gpuskeletal = false;
7060 switch(vid.renderpath)
7062 case RENDERPATH_GL20:
7063 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7064 case RENDERPATH_D3D9:
7065 case RENDERPATH_D3D10:
7066 case RENDERPATH_D3D11:
7067 case RENDERPATH_SOFT:
7068 case RENDERPATH_GLES2:
7069 if(v_glslgamma.integer && !vid_gammatables_trivial)
7071 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7073 // build GLSL gamma texture
7074 #define RAMPWIDTH 256
7075 unsigned short ramp[RAMPWIDTH * 3];
7076 unsigned char rampbgr[RAMPWIDTH][4];
7079 r_texture_gammaramps_serial = vid_gammatables_serial;
7081 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7082 for(i = 0; i < RAMPWIDTH; ++i)
7084 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7085 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7086 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7089 if (r_texture_gammaramps)
7091 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7095 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7101 // remove GLSL gamma texture
7104 case RENDERPATH_GL11:
7105 case RENDERPATH_GL13:
7106 case RENDERPATH_GLES1:
7111 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7112 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7118 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7119 if( scenetype != r_currentscenetype ) {
7120 // store the old scenetype
7121 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7122 r_currentscenetype = scenetype;
7123 // move in the new scene
7124 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7133 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7135 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7136 if( scenetype == r_currentscenetype ) {
7137 return &r_refdef.scene;
7139 return &r_scenes_store[ scenetype ];
7143 static int R_SortEntities_Compare(const void *ap, const void *bp)
7145 const entity_render_t *a = *(const entity_render_t **)ap;
7146 const entity_render_t *b = *(const entity_render_t **)bp;
7149 if(a->model < b->model)
7151 if(a->model > b->model)
7155 // TODO possibly calculate the REAL skinnum here first using
7157 if(a->skinnum < b->skinnum)
7159 if(a->skinnum > b->skinnum)
7162 // everything we compared is equal
7165 static void R_SortEntities(void)
7167 // below or equal 2 ents, sorting never gains anything
7168 if(r_refdef.scene.numentities <= 2)
7171 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7179 int dpsoftrast_test;
7180 extern cvar_t r_shadow_bouncegrid;
7181 void R_RenderView(void)
7183 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7185 rtexture_t *depthtexture;
7186 rtexture_t *colortexture;
7188 dpsoftrast_test = r_test.integer;
7190 if (r_timereport_active)
7191 R_TimeReport("start");
7192 r_textureframe++; // used only by R_GetCurrentTexture
7193 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7195 if(R_CompileShader_CheckStaticParms())
7198 if (!r_drawentities.integer)
7199 r_refdef.scene.numentities = 0;
7200 else if (r_sortentities.integer)
7203 R_AnimCache_ClearCache();
7204 R_FrameData_NewFrame();
7205 R_BufferData_NewFrame();
7207 /* adjust for stereo display */
7208 if(R_Stereo_Active())
7210 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);
7211 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7214 if (r_refdef.view.isoverlay)
7216 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7217 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7218 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7219 R_TimeReport("depthclear");
7221 r_refdef.view.showdebug = false;
7223 r_fb.water.enabled = false;
7224 r_fb.water.numwaterplanes = 0;
7226 R_RenderScene(0, NULL, NULL);
7228 r_refdef.view.matrix = originalmatrix;
7234 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7236 r_refdef.view.matrix = originalmatrix;
7240 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7242 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7243 // in sRGB fallback, behave similar to true sRGB: convert this
7244 // value from linear to sRGB
7245 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7247 R_RenderView_UpdateViewVectors();
7249 R_Shadow_UpdateWorldLightSelection();
7251 R_Bloom_StartFrame();
7253 // apply bloom brightness offset
7254 if(r_fb.bloomtexture[0])
7255 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7257 R_Water_StartFrame();
7259 // now we probably have an fbo to render into
7261 depthtexture = r_fb.depthtexture;
7262 colortexture = r_fb.colortexture;
7265 if (r_timereport_active)
7266 R_TimeReport("viewsetup");
7268 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7270 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7272 R_ClearScreen(r_refdef.fogenabled);
7273 if (r_timereport_active)
7274 R_TimeReport("viewclear");
7276 r_refdef.view.clear = true;
7278 r_refdef.view.showdebug = true;
7281 if (r_timereport_active)
7282 R_TimeReport("visibility");
7284 R_AnimCache_CacheVisibleEntities();
7285 if (r_timereport_active)
7286 R_TimeReport("animcache");
7288 R_Shadow_UpdateBounceGridTexture();
7289 if (r_timereport_active && r_shadow_bouncegrid.integer)
7290 R_TimeReport("bouncegrid");
7292 r_fb.water.numwaterplanes = 0;
7293 if (r_fb.water.enabled)
7294 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7296 R_RenderScene(fbo, depthtexture, colortexture);
7297 r_fb.water.numwaterplanes = 0;
7299 R_BlendView(fbo, depthtexture, colortexture);
7300 if (r_timereport_active)
7301 R_TimeReport("blendview");
7303 GL_Scissor(0, 0, vid.width, vid.height);
7304 GL_ScissorTest(false);
7306 r_refdef.view.matrix = originalmatrix;
7311 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7313 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7315 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7316 if (r_timereport_active)
7317 R_TimeReport("waterworld");
7320 // don't let sound skip if going slow
7321 if (r_refdef.scene.extraupdate)
7324 R_DrawModelsAddWaterPlanes();
7325 if (r_timereport_active)
7326 R_TimeReport("watermodels");
7328 if (r_fb.water.numwaterplanes)
7330 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7331 if (r_timereport_active)
7332 R_TimeReport("waterscenes");
7336 extern cvar_t cl_locs_show;
7337 static void R_DrawLocs(void);
7338 static void R_DrawEntityBBoxes(void);
7339 static void R_DrawModelDecals(void);
7340 extern cvar_t cl_decals_newsystem;
7341 extern qboolean r_shadow_usingdeferredprepass;
7342 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7344 qboolean shadowmapping = false;
7346 if (r_timereport_active)
7347 R_TimeReport("beginscene");
7349 r_refdef.stats[r_stat_renders]++;
7353 // don't let sound skip if going slow
7354 if (r_refdef.scene.extraupdate)
7357 R_MeshQueue_BeginScene();
7361 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);
7363 if (r_timereport_active)
7364 R_TimeReport("skystartframe");
7366 if (cl.csqc_vidvars.drawworld)
7368 // don't let sound skip if going slow
7369 if (r_refdef.scene.extraupdate)
7372 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7374 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7375 if (r_timereport_active)
7376 R_TimeReport("worldsky");
7379 if (R_DrawBrushModelsSky() && r_timereport_active)
7380 R_TimeReport("bmodelsky");
7382 if (skyrendermasked && skyrenderlater)
7384 // we have to force off the water clipping plane while rendering sky
7385 R_SetupView(false, fbo, depthtexture, colortexture);
7387 R_SetupView(true, fbo, depthtexture, colortexture);
7388 if (r_timereport_active)
7389 R_TimeReport("sky");
7393 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7394 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7395 R_Shadow_PrepareModelShadows();
7396 if (r_timereport_active)
7397 R_TimeReport("preparelights");
7399 if (R_Shadow_ShadowMappingEnabled())
7400 shadowmapping = true;
7402 if (r_shadow_usingdeferredprepass)
7403 R_Shadow_DrawPrepass();
7405 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7407 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7408 if (r_timereport_active)
7409 R_TimeReport("worlddepth");
7411 if (r_depthfirst.integer >= 2)
7413 R_DrawModelsDepth();
7414 if (r_timereport_active)
7415 R_TimeReport("modeldepth");
7418 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7420 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7421 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7422 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7423 // don't let sound skip if going slow
7424 if (r_refdef.scene.extraupdate)
7428 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7430 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7431 if (r_timereport_active)
7432 R_TimeReport("world");
7435 // don't let sound skip if going slow
7436 if (r_refdef.scene.extraupdate)
7440 if (r_timereport_active)
7441 R_TimeReport("models");
7443 // don't let sound skip if going slow
7444 if (r_refdef.scene.extraupdate)
7447 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7449 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7450 R_DrawModelShadows(fbo, depthtexture, colortexture);
7451 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7452 // don't let sound skip if going slow
7453 if (r_refdef.scene.extraupdate)
7457 if (!r_shadow_usingdeferredprepass)
7459 R_Shadow_DrawLights();
7460 if (r_timereport_active)
7461 R_TimeReport("rtlights");
7464 // don't let sound skip if going slow
7465 if (r_refdef.scene.extraupdate)
7468 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7470 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7471 R_DrawModelShadows(fbo, depthtexture, colortexture);
7472 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7473 // don't let sound skip if going slow
7474 if (r_refdef.scene.extraupdate)
7478 if (cl.csqc_vidvars.drawworld)
7480 if (cl_decals_newsystem.integer)
7482 R_DrawModelDecals();
7483 if (r_timereport_active)
7484 R_TimeReport("modeldecals");
7489 if (r_timereport_active)
7490 R_TimeReport("decals");
7494 if (r_timereport_active)
7495 R_TimeReport("particles");
7498 if (r_timereport_active)
7499 R_TimeReport("explosions");
7501 R_DrawLightningBeams();
7502 if (r_timereport_active)
7503 R_TimeReport("lightning");
7507 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7509 if (r_refdef.view.showdebug)
7511 if (cl_locs_show.integer)
7514 if (r_timereport_active)
7515 R_TimeReport("showlocs");
7518 if (r_drawportals.integer)
7521 if (r_timereport_active)
7522 R_TimeReport("portals");
7525 if (r_showbboxes.value > 0)
7527 R_DrawEntityBBoxes();
7528 if (r_timereport_active)
7529 R_TimeReport("bboxes");
7533 if (r_transparent.integer)
7535 R_MeshQueue_RenderTransparent();
7536 if (r_timereport_active)
7537 R_TimeReport("drawtrans");
7540 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))
7542 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7543 if (r_timereport_active)
7544 R_TimeReport("worlddebug");
7545 R_DrawModelsDebug();
7546 if (r_timereport_active)
7547 R_TimeReport("modeldebug");
7550 if (cl.csqc_vidvars.drawworld)
7552 R_Shadow_DrawCoronas();
7553 if (r_timereport_active)
7554 R_TimeReport("coronas");
7559 GL_DepthTest(false);
7560 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7561 GL_Color(1, 1, 1, 1);
7562 qglBegin(GL_POLYGON);
7563 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7564 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7565 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7566 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7568 qglBegin(GL_POLYGON);
7569 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]);
7570 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]);
7571 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]);
7572 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]);
7574 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7578 // don't let sound skip if going slow
7579 if (r_refdef.scene.extraupdate)
7583 static const unsigned short bboxelements[36] =
7593 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7596 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7598 RSurf_ActiveWorldEntity();
7600 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7601 GL_DepthMask(false);
7602 GL_DepthRange(0, 1);
7603 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7604 // R_Mesh_ResetTextureState();
7606 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7607 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7608 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7609 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7610 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7611 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7612 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7613 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7614 R_FillColors(color4f, 8, cr, cg, cb, ca);
7615 if (r_refdef.fogenabled)
7617 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7619 f1 = RSurf_FogVertex(v);
7621 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7622 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7623 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7626 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7627 R_Mesh_ResetTextureState();
7628 R_SetupShader_Generic_NoTexture(false, false);
7629 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7632 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7634 prvm_prog_t *prog = SVVM_prog;
7637 prvm_edict_t *edict;
7639 // this function draws bounding boxes of server entities
7643 GL_CullFace(GL_NONE);
7644 R_SetupShader_Generic_NoTexture(false, false);
7646 for (i = 0;i < numsurfaces;i++)
7648 edict = PRVM_EDICT_NUM(surfacelist[i]);
7649 switch ((int)PRVM_serveredictfloat(edict, solid))
7651 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7652 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7653 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7654 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7655 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7656 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7657 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7659 color[3] *= r_showbboxes.value;
7660 color[3] = bound(0, color[3], 1);
7661 GL_DepthTest(!r_showdisabledepthtest.integer);
7662 GL_CullFace(r_refdef.view.cullface_front);
7663 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7667 static void R_DrawEntityBBoxes(void)
7670 prvm_edict_t *edict;
7672 prvm_prog_t *prog = SVVM_prog;
7674 // this function draws bounding boxes of server entities
7678 for (i = 0;i < prog->num_edicts;i++)
7680 edict = PRVM_EDICT_NUM(i);
7681 if (edict->priv.server->free)
7683 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7684 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7686 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7688 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7689 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7693 static const int nomodelelement3i[24] =
7705 static const unsigned short nomodelelement3s[24] =
7717 static const float nomodelvertex3f[6*3] =
7727 static const float nomodelcolor4f[6*4] =
7729 0.0f, 0.0f, 0.5f, 1.0f,
7730 0.0f, 0.0f, 0.5f, 1.0f,
7731 0.0f, 0.5f, 0.0f, 1.0f,
7732 0.0f, 0.5f, 0.0f, 1.0f,
7733 0.5f, 0.0f, 0.0f, 1.0f,
7734 0.5f, 0.0f, 0.0f, 1.0f
7737 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7743 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);
7745 // this is only called once per entity so numsurfaces is always 1, and
7746 // surfacelist is always {0}, so this code does not handle batches
7748 if (rsurface.ent_flags & RENDER_ADDITIVE)
7750 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7751 GL_DepthMask(false);
7753 else if (rsurface.colormod[3] < 1)
7755 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7756 GL_DepthMask(false);
7760 GL_BlendFunc(GL_ONE, GL_ZERO);
7763 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7764 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7765 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7766 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7767 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7768 for (i = 0, c = color4f;i < 6;i++, c += 4)
7770 c[0] *= rsurface.colormod[0];
7771 c[1] *= rsurface.colormod[1];
7772 c[2] *= rsurface.colormod[2];
7773 c[3] *= rsurface.colormod[3];
7775 if (r_refdef.fogenabled)
7777 for (i = 0, c = color4f;i < 6;i++, c += 4)
7779 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7781 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7782 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7783 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7786 // R_Mesh_ResetTextureState();
7787 R_SetupShader_Generic_NoTexture(false, false);
7788 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7789 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7792 void R_DrawNoModel(entity_render_t *ent)
7795 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7796 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7797 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7799 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7802 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7804 vec3_t right1, right2, diff, normal;
7806 VectorSubtract (org2, org1, normal);
7808 // calculate 'right' vector for start
7809 VectorSubtract (r_refdef.view.origin, org1, diff);
7810 CrossProduct (normal, diff, right1);
7811 VectorNormalize (right1);
7813 // calculate 'right' vector for end
7814 VectorSubtract (r_refdef.view.origin, org2, diff);
7815 CrossProduct (normal, diff, right2);
7816 VectorNormalize (right2);
7818 vert[ 0] = org1[0] + width * right1[0];
7819 vert[ 1] = org1[1] + width * right1[1];
7820 vert[ 2] = org1[2] + width * right1[2];
7821 vert[ 3] = org1[0] - width * right1[0];
7822 vert[ 4] = org1[1] - width * right1[1];
7823 vert[ 5] = org1[2] - width * right1[2];
7824 vert[ 6] = org2[0] - width * right2[0];
7825 vert[ 7] = org2[1] - width * right2[1];
7826 vert[ 8] = org2[2] - width * right2[2];
7827 vert[ 9] = org2[0] + width * right2[0];
7828 vert[10] = org2[1] + width * right2[1];
7829 vert[11] = org2[2] + width * right2[2];
7832 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)
7834 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7835 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7836 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7837 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7838 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7839 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7840 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7841 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7842 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7843 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7844 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7845 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7848 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7853 VectorSet(v, x, y, z);
7854 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7855 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7857 if (i == mesh->numvertices)
7859 if (mesh->numvertices < mesh->maxvertices)
7861 VectorCopy(v, vertex3f);
7862 mesh->numvertices++;
7864 return mesh->numvertices;
7870 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7874 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7875 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7876 e = mesh->element3i + mesh->numtriangles * 3;
7877 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7879 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7880 if (mesh->numtriangles < mesh->maxtriangles)
7885 mesh->numtriangles++;
7887 element[1] = element[2];
7891 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7895 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7896 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7897 e = mesh->element3i + mesh->numtriangles * 3;
7898 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7900 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7901 if (mesh->numtriangles < mesh->maxtriangles)
7906 mesh->numtriangles++;
7908 element[1] = element[2];
7912 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7913 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7915 int planenum, planenum2;
7918 mplane_t *plane, *plane2;
7920 double temppoints[2][256*3];
7921 // figure out how large a bounding box we need to properly compute this brush
7923 for (w = 0;w < numplanes;w++)
7924 maxdist = max(maxdist, fabs(planes[w].dist));
7925 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7926 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7927 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7931 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7932 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7934 if (planenum2 == planenum)
7936 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);
7939 if (tempnumpoints < 3)
7941 // generate elements forming a triangle fan for this polygon
7942 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7946 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)
7948 texturelayer_t *layer;
7949 layer = t->currentlayers + t->currentnumlayers++;
7951 layer->depthmask = depthmask;
7952 layer->blendfunc1 = blendfunc1;
7953 layer->blendfunc2 = blendfunc2;
7954 layer->texture = texture;
7955 layer->texmatrix = *matrix;
7956 layer->color[0] = r;
7957 layer->color[1] = g;
7958 layer->color[2] = b;
7959 layer->color[3] = a;
7962 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7964 if(parms[0] == 0 && parms[1] == 0)
7966 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7967 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7972 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7975 index = parms[2] + rsurface.shadertime * parms[3];
7976 index -= floor(index);
7977 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7980 case Q3WAVEFUNC_NONE:
7981 case Q3WAVEFUNC_NOISE:
7982 case Q3WAVEFUNC_COUNT:
7985 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7986 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7987 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7988 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7989 case Q3WAVEFUNC_TRIANGLE:
7991 f = index - floor(index);
8004 f = parms[0] + parms[1] * f;
8005 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8006 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8010 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8016 matrix4x4_t matrix, temp;
8017 switch(tcmod->tcmod)
8021 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8022 matrix = r_waterscrollmatrix;
8024 matrix = identitymatrix;
8026 case Q3TCMOD_ENTITYTRANSLATE:
8027 // this is used in Q3 to allow the gamecode to control texcoord
8028 // scrolling on the entity, which is not supported in darkplaces yet.
8029 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8031 case Q3TCMOD_ROTATE:
8032 f = tcmod->parms[0] * rsurface.shadertime;
8033 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8034 Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
8035 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8038 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8040 case Q3TCMOD_SCROLL:
8041 // extra care is needed because of precision breakdown with large values of time
8042 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8043 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8044 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8046 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8047 w = (int) tcmod->parms[0];
8048 h = (int) tcmod->parms[1];
8049 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8051 idx = (int) floor(f * w * h);
8052 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8054 case Q3TCMOD_STRETCH:
8055 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8056 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8058 case Q3TCMOD_TRANSFORM:
8059 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8060 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8061 VectorSet(tcmat + 6, 0 , 0 , 1);
8062 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8063 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8065 case Q3TCMOD_TURBULENT:
8066 // this is handled in the RSurf_PrepareVertices function
8067 matrix = identitymatrix;
8071 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8074 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8076 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8077 char name[MAX_QPATH];
8078 skinframe_t *skinframe;
8079 unsigned char pixels[296*194];
8080 strlcpy(cache->name, skinname, sizeof(cache->name));
8081 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8082 if (developer_loading.integer)
8083 Con_Printf("loading %s\n", name);
8084 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8085 if (!skinframe || !skinframe->base)
8088 fs_offset_t filesize;
8090 f = FS_LoadFile(name, tempmempool, true, &filesize);
8093 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8094 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8098 cache->skinframe = skinframe;
8101 texture_t *R_GetCurrentTexture(texture_t *t)
8104 const entity_render_t *ent = rsurface.entity;
8105 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8106 q3shaderinfo_layer_tcmod_t *tcmod;
8108 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8109 return t->currentframe;
8110 t->update_lastrenderframe = r_textureframe;
8111 t->update_lastrenderentity = (void *)ent;
8113 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8114 t->camera_entity = ent->entitynumber;
8116 t->camera_entity = 0;
8118 // switch to an alternate material if this is a q1bsp animated material
8120 texture_t *texture = t;
8121 int s = rsurface.ent_skinnum;
8122 if ((unsigned int)s >= (unsigned int)model->numskins)
8124 if (model->skinscenes)
8126 if (model->skinscenes[s].framecount > 1)
8127 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8129 s = model->skinscenes[s].firstframe;
8132 t = t + s * model->num_surfaces;
8135 // use an alternate animation if the entity's frame is not 0,
8136 // and only if the texture has an alternate animation
8137 if (rsurface.ent_alttextures && t->anim_total[1])
8138 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8140 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8142 texture->currentframe = t;
8145 // update currentskinframe to be a qw skin or animation frame
8146 if (rsurface.ent_qwskin >= 0)
8148 i = rsurface.ent_qwskin;
8149 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8151 r_qwskincache_size = cl.maxclients;
8153 Mem_Free(r_qwskincache);
8154 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8156 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8157 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8158 t->currentskinframe = r_qwskincache[i].skinframe;
8159 if (t->currentskinframe == NULL)
8160 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8162 else if (t->numskinframes >= 2)
8163 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8164 if (t->backgroundnumskinframes >= 2)
8165 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8167 t->currentmaterialflags = t->basematerialflags;
8168 t->currentalpha = rsurface.colormod[3];
8169 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8170 t->currentalpha *= r_wateralpha.value;
8171 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8172 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8173 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8174 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8175 if (!(rsurface.ent_flags & RENDER_LIGHT))
8176 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8177 else if (FAKELIGHT_ENABLED)
8179 // no modellight if using fakelight for the map
8181 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8183 // pick a model lighting mode
8184 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8185 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8187 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8189 if (rsurface.ent_flags & RENDER_ADDITIVE)
8190 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8191 else if (t->currentalpha < 1)
8192 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8193 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8194 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8195 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8196 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8197 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8198 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8199 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8200 if (t->backgroundnumskinframes)
8201 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8202 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8204 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8205 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8208 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8209 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8211 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8212 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8214 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8215 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8217 // there is no tcmod
8218 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8220 t->currenttexmatrix = r_waterscrollmatrix;
8221 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8223 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8225 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8226 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8229 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8230 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8231 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8232 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8234 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8235 if (t->currentskinframe->qpixels)
8236 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8237 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8238 if (!t->basetexture)
8239 t->basetexture = r_texture_notexture;
8240 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8241 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8242 t->nmaptexture = t->currentskinframe->nmap;
8243 if (!t->nmaptexture)
8244 t->nmaptexture = r_texture_blanknormalmap;
8245 t->glosstexture = r_texture_black;
8246 t->glowtexture = t->currentskinframe->glow;
8247 t->fogtexture = t->currentskinframe->fog;
8248 t->reflectmasktexture = t->currentskinframe->reflect;
8249 if (t->backgroundnumskinframes)
8251 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8252 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8253 t->backgroundglosstexture = r_texture_black;
8254 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8255 if (!t->backgroundnmaptexture)
8256 t->backgroundnmaptexture = r_texture_blanknormalmap;
8257 // make sure that if glow is going to be used, both textures are not NULL
8258 if (!t->backgroundglowtexture && t->glowtexture)
8259 t->backgroundglowtexture = r_texture_black;
8260 if (!t->glowtexture && t->backgroundglowtexture)
8261 t->glowtexture = r_texture_black;
8265 t->backgroundbasetexture = r_texture_white;
8266 t->backgroundnmaptexture = r_texture_blanknormalmap;
8267 t->backgroundglosstexture = r_texture_black;
8268 t->backgroundglowtexture = NULL;
8270 t->specularpower = r_shadow_glossexponent.value;
8271 // TODO: store reference values for these in the texture?
8272 t->specularscale = 0;
8273 if (r_shadow_gloss.integer > 0)
8275 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8277 if (r_shadow_glossintensity.value > 0)
8279 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8280 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8281 t->specularscale = r_shadow_glossintensity.value;
8284 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8286 t->glosstexture = r_texture_white;
8287 t->backgroundglosstexture = r_texture_white;
8288 t->specularscale = r_shadow_gloss2intensity.value;
8289 t->specularpower = r_shadow_gloss2exponent.value;
8292 t->specularscale *= t->specularscalemod;
8293 t->specularpower *= t->specularpowermod;
8294 t->rtlightambient = 0;
8296 // lightmaps mode looks bad with dlights using actual texturing, so turn
8297 // off the colormap and glossmap, but leave the normalmap on as it still
8298 // accurately represents the shading involved
8299 if (gl_lightmaps.integer)
8301 t->basetexture = r_texture_grey128;
8302 t->pantstexture = r_texture_black;
8303 t->shirttexture = r_texture_black;
8304 if (gl_lightmaps.integer < 2)
8305 t->nmaptexture = r_texture_blanknormalmap;
8306 t->glosstexture = r_texture_black;
8307 t->glowtexture = NULL;
8308 t->fogtexture = NULL;
8309 t->reflectmasktexture = NULL;
8310 t->backgroundbasetexture = NULL;
8311 if (gl_lightmaps.integer < 2)
8312 t->backgroundnmaptexture = r_texture_blanknormalmap;
8313 t->backgroundglosstexture = r_texture_black;
8314 t->backgroundglowtexture = NULL;
8315 t->specularscale = 0;
8316 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8319 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8320 VectorClear(t->dlightcolor);
8321 t->currentnumlayers = 0;
8322 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8324 int blendfunc1, blendfunc2;
8326 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8328 blendfunc1 = GL_SRC_ALPHA;
8329 blendfunc2 = GL_ONE;
8331 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8333 blendfunc1 = GL_SRC_ALPHA;
8334 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8336 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8338 blendfunc1 = t->customblendfunc[0];
8339 blendfunc2 = t->customblendfunc[1];
8343 blendfunc1 = GL_ONE;
8344 blendfunc2 = GL_ZERO;
8346 // don't colormod evilblend textures
8347 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8348 VectorSet(t->lightmapcolor, 1, 1, 1);
8349 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8350 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8352 // fullbright is not affected by r_refdef.lightmapintensity
8353 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]);
8354 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8355 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]);
8356 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8357 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]);
8361 vec3_t ambientcolor;
8363 // set the color tint used for lights affecting this surface
8364 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8366 // q3bsp has no lightmap updates, so the lightstylevalue that
8367 // would normally be baked into the lightmap must be
8368 // applied to the color
8369 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8370 if (model->type == mod_brushq3)
8371 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8372 colorscale *= r_refdef.lightmapintensity;
8373 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8374 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8375 // basic lit geometry
8376 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]);
8377 // add pants/shirt if needed
8378 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8379 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]);
8380 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8381 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]);
8382 // now add ambient passes if needed
8383 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8385 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]);
8386 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8387 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]);
8388 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8389 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]);
8392 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8393 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]);
8394 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8396 // if this is opaque use alpha blend which will darken the earlier
8399 // if this is an alpha blended material, all the earlier passes
8400 // were darkened by fog already, so we only need to add the fog
8401 // color ontop through the fog mask texture
8403 // if this is an additive blended material, all the earlier passes
8404 // were darkened by fog already, and we should not add fog color
8405 // (because the background was not darkened, there is no fog color
8406 // that was lost behind it).
8407 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]);
8411 return t->currentframe;
8414 rsurfacestate_t rsurface;
8416 void RSurf_ActiveWorldEntity(void)
8418 dp_model_t *model = r_refdef.scene.worldmodel;
8419 //if (rsurface.entity == r_refdef.scene.worldentity)
8421 rsurface.entity = r_refdef.scene.worldentity;
8422 rsurface.skeleton = NULL;
8423 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8424 rsurface.ent_skinnum = 0;
8425 rsurface.ent_qwskin = -1;
8426 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8427 rsurface.shadertime = r_refdef.scene.time;
8428 rsurface.matrix = identitymatrix;
8429 rsurface.inversematrix = identitymatrix;
8430 rsurface.matrixscale = 1;
8431 rsurface.inversematrixscale = 1;
8432 R_EntityMatrix(&identitymatrix);
8433 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8434 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8435 rsurface.fograngerecip = r_refdef.fograngerecip;
8436 rsurface.fogheightfade = r_refdef.fogheightfade;
8437 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8438 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8439 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8440 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8441 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8442 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8443 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8444 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8445 rsurface.colormod[3] = 1;
8446 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);
8447 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8448 rsurface.frameblend[0].lerp = 1;
8449 rsurface.ent_alttextures = false;
8450 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8451 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8452 rsurface.entityskeletaltransform3x4 = NULL;
8453 rsurface.entityskeletaltransform3x4buffer = NULL;
8454 rsurface.entityskeletaltransform3x4offset = 0;
8455 rsurface.entityskeletaltransform3x4size = 0;;
8456 rsurface.entityskeletalnumtransforms = 0;
8457 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8458 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8459 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8460 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8461 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8462 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8463 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8464 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8465 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8466 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8467 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8468 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8469 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8470 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8471 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8472 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8473 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8475 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8476 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8477 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8478 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8479 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8480 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8481 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8482 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8484 rsurface.modelelement3i = model->surfmesh.data_element3i;
8485 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8486 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8487 rsurface.modelelement3s = model->surfmesh.data_element3s;
8488 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8489 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8490 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8491 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8492 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8493 rsurface.modelsurfaces = model->data_surfaces;
8494 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8495 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8496 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8497 rsurface.modelgeneratedvertex = false;
8498 rsurface.batchgeneratedvertex = false;
8499 rsurface.batchfirstvertex = 0;
8500 rsurface.batchnumvertices = 0;
8501 rsurface.batchfirsttriangle = 0;
8502 rsurface.batchnumtriangles = 0;
8503 rsurface.batchvertex3f = NULL;
8504 rsurface.batchvertex3f_vertexbuffer = NULL;
8505 rsurface.batchvertex3f_bufferoffset = 0;
8506 rsurface.batchsvector3f = NULL;
8507 rsurface.batchsvector3f_vertexbuffer = NULL;
8508 rsurface.batchsvector3f_bufferoffset = 0;
8509 rsurface.batchtvector3f = NULL;
8510 rsurface.batchtvector3f_vertexbuffer = NULL;
8511 rsurface.batchtvector3f_bufferoffset = 0;
8512 rsurface.batchnormal3f = NULL;
8513 rsurface.batchnormal3f_vertexbuffer = NULL;
8514 rsurface.batchnormal3f_bufferoffset = 0;
8515 rsurface.batchlightmapcolor4f = NULL;
8516 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8517 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8518 rsurface.batchtexcoordtexture2f = NULL;
8519 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8520 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8521 rsurface.batchtexcoordlightmap2f = NULL;
8522 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8523 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8524 rsurface.batchskeletalindex4ub = NULL;
8525 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8526 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8527 rsurface.batchskeletalweight4ub = NULL;
8528 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8529 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8530 rsurface.batchvertexmesh = NULL;
8531 rsurface.batchvertexmesh_vertexbuffer = NULL;
8532 rsurface.batchvertexmesh_bufferoffset = 0;
8533 rsurface.batchelement3i = NULL;
8534 rsurface.batchelement3i_indexbuffer = NULL;
8535 rsurface.batchelement3i_bufferoffset = 0;
8536 rsurface.batchelement3s = NULL;
8537 rsurface.batchelement3s_indexbuffer = NULL;
8538 rsurface.batchelement3s_bufferoffset = 0;
8539 rsurface.passcolor4f = NULL;
8540 rsurface.passcolor4f_vertexbuffer = NULL;
8541 rsurface.passcolor4f_bufferoffset = 0;
8542 rsurface.forcecurrenttextureupdate = false;
8545 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8547 dp_model_t *model = ent->model;
8548 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8550 rsurface.entity = (entity_render_t *)ent;
8551 rsurface.skeleton = ent->skeleton;
8552 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8553 rsurface.ent_skinnum = ent->skinnum;
8554 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;
8555 rsurface.ent_flags = ent->flags;
8556 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8557 rsurface.matrix = ent->matrix;
8558 rsurface.inversematrix = ent->inversematrix;
8559 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8560 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8561 R_EntityMatrix(&rsurface.matrix);
8562 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8563 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8564 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8565 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8566 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8567 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8568 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8569 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8570 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8571 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8572 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8573 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8574 rsurface.colormod[3] = ent->alpha;
8575 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8576 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8577 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8578 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8579 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8580 if (ent->model->brush.submodel && !prepass)
8582 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8583 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8585 // if the animcache code decided it should use the shader path, skip the deform step
8586 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8587 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8588 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8589 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8590 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8591 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8593 if (ent->animcache_vertex3f)
8595 r_refdef.stats[r_stat_batch_entitycache_count]++;
8596 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8597 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8598 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8599 rsurface.modelvertex3f = ent->animcache_vertex3f;
8600 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8601 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8602 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8603 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8604 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8605 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8606 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8607 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8608 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8609 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8610 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8611 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8612 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8613 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8615 else if (wanttangents)
8617 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8618 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8619 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8620 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8621 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8622 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8623 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8624 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8625 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8626 rsurface.modelvertexmesh = NULL;
8627 rsurface.modelvertexmesh_vertexbuffer = NULL;
8628 rsurface.modelvertexmesh_bufferoffset = 0;
8629 rsurface.modelvertex3f_vertexbuffer = NULL;
8630 rsurface.modelvertex3f_bufferoffset = 0;
8631 rsurface.modelvertex3f_vertexbuffer = 0;
8632 rsurface.modelvertex3f_bufferoffset = 0;
8633 rsurface.modelsvector3f_vertexbuffer = 0;
8634 rsurface.modelsvector3f_bufferoffset = 0;
8635 rsurface.modeltvector3f_vertexbuffer = 0;
8636 rsurface.modeltvector3f_bufferoffset = 0;
8637 rsurface.modelnormal3f_vertexbuffer = 0;
8638 rsurface.modelnormal3f_bufferoffset = 0;
8640 else if (wantnormals)
8642 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8643 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8644 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8645 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8646 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8647 rsurface.modelsvector3f = NULL;
8648 rsurface.modeltvector3f = NULL;
8649 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8650 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8651 rsurface.modelvertexmesh = NULL;
8652 rsurface.modelvertexmesh_vertexbuffer = NULL;
8653 rsurface.modelvertexmesh_bufferoffset = 0;
8654 rsurface.modelvertex3f_vertexbuffer = NULL;
8655 rsurface.modelvertex3f_bufferoffset = 0;
8656 rsurface.modelvertex3f_vertexbuffer = 0;
8657 rsurface.modelvertex3f_bufferoffset = 0;
8658 rsurface.modelsvector3f_vertexbuffer = 0;
8659 rsurface.modelsvector3f_bufferoffset = 0;
8660 rsurface.modeltvector3f_vertexbuffer = 0;
8661 rsurface.modeltvector3f_bufferoffset = 0;
8662 rsurface.modelnormal3f_vertexbuffer = 0;
8663 rsurface.modelnormal3f_bufferoffset = 0;
8667 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8668 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8669 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8670 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8671 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8672 rsurface.modelsvector3f = NULL;
8673 rsurface.modeltvector3f = NULL;
8674 rsurface.modelnormal3f = NULL;
8675 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8676 rsurface.modelvertexmesh = NULL;
8677 rsurface.modelvertexmesh_vertexbuffer = NULL;
8678 rsurface.modelvertexmesh_bufferoffset = 0;
8679 rsurface.modelvertex3f_vertexbuffer = NULL;
8680 rsurface.modelvertex3f_bufferoffset = 0;
8681 rsurface.modelvertex3f_vertexbuffer = 0;
8682 rsurface.modelvertex3f_bufferoffset = 0;
8683 rsurface.modelsvector3f_vertexbuffer = 0;
8684 rsurface.modelsvector3f_bufferoffset = 0;
8685 rsurface.modeltvector3f_vertexbuffer = 0;
8686 rsurface.modeltvector3f_bufferoffset = 0;
8687 rsurface.modelnormal3f_vertexbuffer = 0;
8688 rsurface.modelnormal3f_bufferoffset = 0;
8690 rsurface.modelgeneratedvertex = true;
8694 if (rsurface.entityskeletaltransform3x4)
8696 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8697 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8698 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8699 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8703 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8704 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8705 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8706 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8708 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8709 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8710 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8711 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8712 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8713 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8714 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8715 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8716 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8717 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8718 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8719 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8720 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8721 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8722 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8723 rsurface.modelgeneratedvertex = false;
8725 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8726 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8727 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8728 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8729 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8730 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8731 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8732 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8733 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8734 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8735 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8736 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8737 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8738 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8739 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8740 rsurface.modelelement3i = model->surfmesh.data_element3i;
8741 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8742 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8743 rsurface.modelelement3s = model->surfmesh.data_element3s;
8744 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8745 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8746 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8747 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8748 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8749 rsurface.modelsurfaces = model->data_surfaces;
8750 rsurface.batchgeneratedvertex = false;
8751 rsurface.batchfirstvertex = 0;
8752 rsurface.batchnumvertices = 0;
8753 rsurface.batchfirsttriangle = 0;
8754 rsurface.batchnumtriangles = 0;
8755 rsurface.batchvertex3f = NULL;
8756 rsurface.batchvertex3f_vertexbuffer = NULL;
8757 rsurface.batchvertex3f_bufferoffset = 0;
8758 rsurface.batchsvector3f = NULL;
8759 rsurface.batchsvector3f_vertexbuffer = NULL;
8760 rsurface.batchsvector3f_bufferoffset = 0;
8761 rsurface.batchtvector3f = NULL;
8762 rsurface.batchtvector3f_vertexbuffer = NULL;
8763 rsurface.batchtvector3f_bufferoffset = 0;
8764 rsurface.batchnormal3f = NULL;
8765 rsurface.batchnormal3f_vertexbuffer = NULL;
8766 rsurface.batchnormal3f_bufferoffset = 0;
8767 rsurface.batchlightmapcolor4f = NULL;
8768 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8769 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8770 rsurface.batchtexcoordtexture2f = NULL;
8771 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8772 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8773 rsurface.batchtexcoordlightmap2f = NULL;
8774 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8775 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8776 rsurface.batchskeletalindex4ub = NULL;
8777 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8778 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8779 rsurface.batchskeletalweight4ub = NULL;
8780 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8781 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8782 rsurface.batchvertexmesh = NULL;
8783 rsurface.batchvertexmesh_vertexbuffer = NULL;
8784 rsurface.batchvertexmesh_bufferoffset = 0;
8785 rsurface.batchelement3i = NULL;
8786 rsurface.batchelement3i_indexbuffer = NULL;
8787 rsurface.batchelement3i_bufferoffset = 0;
8788 rsurface.batchelement3s = NULL;
8789 rsurface.batchelement3s_indexbuffer = NULL;
8790 rsurface.batchelement3s_bufferoffset = 0;
8791 rsurface.passcolor4f = NULL;
8792 rsurface.passcolor4f_vertexbuffer = NULL;
8793 rsurface.passcolor4f_bufferoffset = 0;
8794 rsurface.forcecurrenttextureupdate = false;
8797 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)
8799 rsurface.entity = r_refdef.scene.worldentity;
8800 rsurface.skeleton = NULL;
8801 rsurface.ent_skinnum = 0;
8802 rsurface.ent_qwskin = -1;
8803 rsurface.ent_flags = entflags;
8804 rsurface.shadertime = r_refdef.scene.time - shadertime;
8805 rsurface.modelnumvertices = numvertices;
8806 rsurface.modelnumtriangles = numtriangles;
8807 rsurface.matrix = *matrix;
8808 rsurface.inversematrix = *inversematrix;
8809 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8810 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8811 R_EntityMatrix(&rsurface.matrix);
8812 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8813 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8814 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8815 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8816 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8817 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8818 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8819 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8820 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8821 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8822 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8823 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8824 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);
8825 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8826 rsurface.frameblend[0].lerp = 1;
8827 rsurface.ent_alttextures = false;
8828 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8829 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8830 rsurface.entityskeletaltransform3x4 = NULL;
8831 rsurface.entityskeletaltransform3x4buffer = NULL;
8832 rsurface.entityskeletaltransform3x4offset = 0;
8833 rsurface.entityskeletaltransform3x4size = 0;
8834 rsurface.entityskeletalnumtransforms = 0;
8835 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8836 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8837 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8838 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8841 rsurface.modelvertex3f = (float *)vertex3f;
8842 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8843 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8844 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8846 else if (wantnormals)
8848 rsurface.modelvertex3f = (float *)vertex3f;
8849 rsurface.modelsvector3f = NULL;
8850 rsurface.modeltvector3f = NULL;
8851 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8855 rsurface.modelvertex3f = (float *)vertex3f;
8856 rsurface.modelsvector3f = NULL;
8857 rsurface.modeltvector3f = NULL;
8858 rsurface.modelnormal3f = NULL;
8860 rsurface.modelvertexmesh = NULL;
8861 rsurface.modelvertexmesh_vertexbuffer = NULL;
8862 rsurface.modelvertexmesh_bufferoffset = 0;
8863 rsurface.modelvertex3f_vertexbuffer = 0;
8864 rsurface.modelvertex3f_bufferoffset = 0;
8865 rsurface.modelsvector3f_vertexbuffer = 0;
8866 rsurface.modelsvector3f_bufferoffset = 0;
8867 rsurface.modeltvector3f_vertexbuffer = 0;
8868 rsurface.modeltvector3f_bufferoffset = 0;
8869 rsurface.modelnormal3f_vertexbuffer = 0;
8870 rsurface.modelnormal3f_bufferoffset = 0;
8871 rsurface.modelgeneratedvertex = true;
8872 rsurface.modellightmapcolor4f = (float *)color4f;
8873 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8874 rsurface.modellightmapcolor4f_bufferoffset = 0;
8875 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8876 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8877 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8878 rsurface.modeltexcoordlightmap2f = NULL;
8879 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8880 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8881 rsurface.modelskeletalindex4ub = NULL;
8882 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8883 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8884 rsurface.modelskeletalweight4ub = NULL;
8885 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8886 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8887 rsurface.modelelement3i = (int *)element3i;
8888 rsurface.modelelement3i_indexbuffer = NULL;
8889 rsurface.modelelement3i_bufferoffset = 0;
8890 rsurface.modelelement3s = (unsigned short *)element3s;
8891 rsurface.modelelement3s_indexbuffer = NULL;
8892 rsurface.modelelement3s_bufferoffset = 0;
8893 rsurface.modellightmapoffsets = NULL;
8894 rsurface.modelsurfaces = NULL;
8895 rsurface.batchgeneratedvertex = false;
8896 rsurface.batchfirstvertex = 0;
8897 rsurface.batchnumvertices = 0;
8898 rsurface.batchfirsttriangle = 0;
8899 rsurface.batchnumtriangles = 0;
8900 rsurface.batchvertex3f = NULL;
8901 rsurface.batchvertex3f_vertexbuffer = NULL;
8902 rsurface.batchvertex3f_bufferoffset = 0;
8903 rsurface.batchsvector3f = NULL;
8904 rsurface.batchsvector3f_vertexbuffer = NULL;
8905 rsurface.batchsvector3f_bufferoffset = 0;
8906 rsurface.batchtvector3f = NULL;
8907 rsurface.batchtvector3f_vertexbuffer = NULL;
8908 rsurface.batchtvector3f_bufferoffset = 0;
8909 rsurface.batchnormal3f = NULL;
8910 rsurface.batchnormal3f_vertexbuffer = NULL;
8911 rsurface.batchnormal3f_bufferoffset = 0;
8912 rsurface.batchlightmapcolor4f = NULL;
8913 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8914 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8915 rsurface.batchtexcoordtexture2f = NULL;
8916 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8917 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8918 rsurface.batchtexcoordlightmap2f = NULL;
8919 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8920 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8921 rsurface.batchskeletalindex4ub = NULL;
8922 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8923 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8924 rsurface.batchskeletalweight4ub = NULL;
8925 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8926 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8927 rsurface.batchvertexmesh = NULL;
8928 rsurface.batchvertexmesh_vertexbuffer = NULL;
8929 rsurface.batchvertexmesh_bufferoffset = 0;
8930 rsurface.batchelement3i = NULL;
8931 rsurface.batchelement3i_indexbuffer = NULL;
8932 rsurface.batchelement3i_bufferoffset = 0;
8933 rsurface.batchelement3s = NULL;
8934 rsurface.batchelement3s_indexbuffer = NULL;
8935 rsurface.batchelement3s_bufferoffset = 0;
8936 rsurface.passcolor4f = NULL;
8937 rsurface.passcolor4f_vertexbuffer = NULL;
8938 rsurface.passcolor4f_bufferoffset = 0;
8939 rsurface.forcecurrenttextureupdate = true;
8941 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8943 if ((wantnormals || wanttangents) && !normal3f)
8945 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8946 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8948 if (wanttangents && !svector3f)
8950 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8951 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8952 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8957 float RSurf_FogPoint(const float *v)
8959 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8960 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8961 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8962 float FogHeightFade = r_refdef.fogheightfade;
8964 unsigned int fogmasktableindex;
8965 if (r_refdef.fogplaneviewabove)
8966 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8968 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8969 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8970 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8973 float RSurf_FogVertex(const float *v)
8975 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8976 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8977 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8978 float FogHeightFade = rsurface.fogheightfade;
8980 unsigned int fogmasktableindex;
8981 if (r_refdef.fogplaneviewabove)
8982 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8984 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8985 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8986 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8989 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8992 for (i = 0;i < numelements;i++)
8993 outelement3i[i] = inelement3i[i] + adjust;
8996 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8997 extern cvar_t gl_vbo;
8998 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9006 int surfacefirsttriangle;
9007 int surfacenumtriangles;
9008 int surfacefirstvertex;
9009 int surfaceendvertex;
9010 int surfacenumvertices;
9011 int batchnumsurfaces = texturenumsurfaces;
9012 int batchnumvertices;
9013 int batchnumtriangles;
9017 qboolean dynamicvertex;
9021 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9024 q3shaderinfo_deform_t *deform;
9025 const msurface_t *surface, *firstsurface;
9026 r_vertexmesh_t *vertexmesh;
9027 if (!texturenumsurfaces)
9029 // find vertex range of this surface batch
9031 firstsurface = texturesurfacelist[0];
9032 firsttriangle = firstsurface->num_firsttriangle;
9033 batchnumvertices = 0;
9034 batchnumtriangles = 0;
9035 firstvertex = endvertex = firstsurface->num_firstvertex;
9036 for (i = 0;i < texturenumsurfaces;i++)
9038 surface = texturesurfacelist[i];
9039 if (surface != firstsurface + i)
9041 surfacefirstvertex = surface->num_firstvertex;
9042 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9043 surfacenumvertices = surface->num_vertices;
9044 surfacenumtriangles = surface->num_triangles;
9045 if (firstvertex > surfacefirstvertex)
9046 firstvertex = surfacefirstvertex;
9047 if (endvertex < surfaceendvertex)
9048 endvertex = surfaceendvertex;
9049 batchnumvertices += surfacenumvertices;
9050 batchnumtriangles += surfacenumtriangles;
9053 r_refdef.stats[r_stat_batch_batches]++;
9055 r_refdef.stats[r_stat_batch_withgaps]++;
9056 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9057 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9058 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9060 // we now know the vertex range used, and if there are any gaps in it
9061 rsurface.batchfirstvertex = firstvertex;
9062 rsurface.batchnumvertices = endvertex - firstvertex;
9063 rsurface.batchfirsttriangle = firsttriangle;
9064 rsurface.batchnumtriangles = batchnumtriangles;
9066 // this variable holds flags for which properties have been updated that
9067 // may require regenerating vertexmesh array...
9070 // check if any dynamic vertex processing must occur
9071 dynamicvertex = false;
9073 // a cvar to force the dynamic vertex path to be taken, for debugging
9074 if (r_batch_debugdynamicvertexpath.integer)
9078 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9079 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9080 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9081 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9083 dynamicvertex = true;
9086 // if there is a chance of animated vertex colors, it's a dynamic batch
9087 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9091 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9092 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9093 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9094 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9096 dynamicvertex = true;
9097 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9100 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9102 switch (deform->deform)
9105 case Q3DEFORM_PROJECTIONSHADOW:
9106 case Q3DEFORM_TEXT0:
9107 case Q3DEFORM_TEXT1:
9108 case Q3DEFORM_TEXT2:
9109 case Q3DEFORM_TEXT3:
9110 case Q3DEFORM_TEXT4:
9111 case Q3DEFORM_TEXT5:
9112 case Q3DEFORM_TEXT6:
9113 case Q3DEFORM_TEXT7:
9116 case Q3DEFORM_AUTOSPRITE:
9119 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9120 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9121 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9122 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9124 dynamicvertex = true;
9125 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9126 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9128 case Q3DEFORM_AUTOSPRITE2:
9131 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9132 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9133 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9134 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9136 dynamicvertex = true;
9137 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9138 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9140 case Q3DEFORM_NORMAL:
9143 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9144 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9145 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9146 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9148 dynamicvertex = true;
9149 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9150 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9153 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9154 break; // if wavefunc is a nop, ignore this transform
9157 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9158 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9159 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9160 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9162 dynamicvertex = true;
9163 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9164 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9166 case Q3DEFORM_BULGE:
9169 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9170 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9171 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9172 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9174 dynamicvertex = true;
9175 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9176 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9179 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9180 break; // if wavefunc is a nop, ignore this transform
9183 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9184 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9185 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9186 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9188 dynamicvertex = true;
9189 batchneed |= BATCHNEED_ARRAY_VERTEX;
9190 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9194 switch(rsurface.texture->tcgen.tcgen)
9197 case Q3TCGEN_TEXTURE:
9199 case Q3TCGEN_LIGHTMAP:
9202 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9203 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9204 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9205 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9207 dynamicvertex = true;
9208 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9209 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9211 case Q3TCGEN_VECTOR:
9214 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9215 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9216 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9217 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9219 dynamicvertex = true;
9220 batchneed |= BATCHNEED_ARRAY_VERTEX;
9221 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9223 case Q3TCGEN_ENVIRONMENT:
9226 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9227 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9228 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9229 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9231 dynamicvertex = true;
9232 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9233 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9236 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9240 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9241 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9242 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9243 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9245 dynamicvertex = true;
9246 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9247 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9250 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9254 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9255 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9256 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9257 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9259 dynamicvertex = true;
9260 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9263 // when the model data has no vertex buffer (dynamic mesh), we need to
9265 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9266 batchneed |= BATCHNEED_NOGAPS;
9268 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9269 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9270 // we ensure this by treating the vertex batch as dynamic...
9271 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9275 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9276 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9277 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9278 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9280 dynamicvertex = true;
9285 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9286 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9287 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9288 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9289 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9290 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9291 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9292 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9295 // if needsupdate, we have to do a dynamic vertex batch for sure
9296 if (needsupdate & batchneed)
9300 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9301 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9302 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9303 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9305 dynamicvertex = true;
9308 // see if we need to build vertexmesh from arrays
9309 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9313 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9314 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9315 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9316 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9318 dynamicvertex = true;
9321 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9322 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9323 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9325 rsurface.batchvertex3f = rsurface.modelvertex3f;
9326 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9327 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9328 rsurface.batchsvector3f = rsurface.modelsvector3f;
9329 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9330 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9331 rsurface.batchtvector3f = rsurface.modeltvector3f;
9332 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9333 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9334 rsurface.batchnormal3f = rsurface.modelnormal3f;
9335 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9336 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9337 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9338 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9339 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9340 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9341 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9342 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9343 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9344 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9345 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9346 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9347 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9348 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9349 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9350 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9351 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9352 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9353 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9354 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9355 rsurface.batchelement3i = rsurface.modelelement3i;
9356 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9357 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9358 rsurface.batchelement3s = rsurface.modelelement3s;
9359 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9360 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9361 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9362 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9363 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9364 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9365 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9367 // if any dynamic vertex processing has to occur in software, we copy the
9368 // entire surface list together before processing to rebase the vertices
9369 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9371 // if any gaps exist and we do not have a static vertex buffer, we have to
9372 // copy the surface list together to avoid wasting upload bandwidth on the
9373 // vertices in the gaps.
9375 // if gaps exist and we have a static vertex buffer, we can choose whether
9376 // to combine the index buffer ranges into one dynamic index buffer or
9377 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9379 // in many cases the batch is reduced to one draw call.
9381 rsurface.batchmultidraw = false;
9382 rsurface.batchmultidrawnumsurfaces = 0;
9383 rsurface.batchmultidrawsurfacelist = NULL;
9387 // static vertex data, just set pointers...
9388 rsurface.batchgeneratedvertex = false;
9389 // if there are gaps, we want to build a combined index buffer,
9390 // otherwise use the original static buffer with an appropriate offset
9393 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9394 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9395 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9396 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9397 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9399 rsurface.batchmultidraw = true;
9400 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9401 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9404 // build a new triangle elements array for this batch
9405 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9406 rsurface.batchfirsttriangle = 0;
9408 for (i = 0;i < texturenumsurfaces;i++)
9410 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9411 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9412 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9413 numtriangles += surfacenumtriangles;
9415 rsurface.batchelement3i_indexbuffer = NULL;
9416 rsurface.batchelement3i_bufferoffset = 0;
9417 rsurface.batchelement3s = NULL;
9418 rsurface.batchelement3s_indexbuffer = NULL;
9419 rsurface.batchelement3s_bufferoffset = 0;
9420 if (endvertex <= 65536)
9422 // make a 16bit (unsigned short) index array if possible
9423 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9424 for (i = 0;i < numtriangles*3;i++)
9425 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9427 // upload buffer data for the copytriangles batch
9428 if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
9430 if (rsurface.batchelement3s)
9431 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset, !vid.forcevbo);
9432 else if (rsurface.batchelement3i)
9433 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset, !vid.forcevbo);
9438 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9439 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9440 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9441 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9446 // something needs software processing, do it for real...
9447 // we only directly handle separate array data in this case and then
9448 // generate interleaved data if needed...
9449 rsurface.batchgeneratedvertex = true;
9450 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9451 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9452 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9453 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9455 // now copy the vertex data into a combined array and make an index array
9456 // (this is what Quake3 does all the time)
9457 // we also apply any skeletal animation here that would have been done in
9458 // the vertex shader, because most of the dynamic vertex animation cases
9459 // need actual vertex positions and normals
9460 //if (dynamicvertex)
9462 rsurface.batchvertexmesh = NULL;
9463 rsurface.batchvertexmesh_vertexbuffer = NULL;
9464 rsurface.batchvertexmesh_bufferoffset = 0;
9465 rsurface.batchvertex3f = NULL;
9466 rsurface.batchvertex3f_vertexbuffer = NULL;
9467 rsurface.batchvertex3f_bufferoffset = 0;
9468 rsurface.batchsvector3f = NULL;
9469 rsurface.batchsvector3f_vertexbuffer = NULL;
9470 rsurface.batchsvector3f_bufferoffset = 0;
9471 rsurface.batchtvector3f = NULL;
9472 rsurface.batchtvector3f_vertexbuffer = NULL;
9473 rsurface.batchtvector3f_bufferoffset = 0;
9474 rsurface.batchnormal3f = NULL;
9475 rsurface.batchnormal3f_vertexbuffer = NULL;
9476 rsurface.batchnormal3f_bufferoffset = 0;
9477 rsurface.batchlightmapcolor4f = NULL;
9478 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9479 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9480 rsurface.batchtexcoordtexture2f = NULL;
9481 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9482 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9483 rsurface.batchtexcoordlightmap2f = NULL;
9484 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9485 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9486 rsurface.batchskeletalindex4ub = NULL;
9487 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9488 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9489 rsurface.batchskeletalweight4ub = NULL;
9490 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9491 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9492 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9493 rsurface.batchelement3i_indexbuffer = NULL;
9494 rsurface.batchelement3i_bufferoffset = 0;
9495 rsurface.batchelement3s = NULL;
9496 rsurface.batchelement3s_indexbuffer = NULL;
9497 rsurface.batchelement3s_bufferoffset = 0;
9498 rsurface.batchskeletaltransform3x4buffer = NULL;
9499 rsurface.batchskeletaltransform3x4offset = 0;
9500 rsurface.batchskeletaltransform3x4size = 0;
9501 // we'll only be setting up certain arrays as needed
9502 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9503 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9504 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9505 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9506 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9507 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9508 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9510 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9511 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9513 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9514 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9515 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9516 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9517 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9518 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9519 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9521 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9522 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9526 for (i = 0;i < texturenumsurfaces;i++)
9528 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9529 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9530 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9531 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9532 // copy only the data requested
9533 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9534 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9535 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9537 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9539 if (rsurface.batchvertex3f)
9540 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9542 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9544 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9546 if (rsurface.modelnormal3f)
9547 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9549 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9551 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9553 if (rsurface.modelsvector3f)
9555 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9556 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9560 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9561 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9564 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9566 if (rsurface.modellightmapcolor4f)
9567 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9569 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9571 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9573 if (rsurface.modeltexcoordtexture2f)
9574 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9576 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9578 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9580 if (rsurface.modeltexcoordlightmap2f)
9581 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9583 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9585 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9587 if (rsurface.modelskeletalindex4ub)
9589 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9590 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9594 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9595 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9596 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9597 for (j = 0;j < surfacenumvertices;j++)
9602 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9603 numvertices += surfacenumvertices;
9604 numtriangles += surfacenumtriangles;
9607 // generate a 16bit index array as well if possible
9608 // (in general, dynamic batches fit)
9609 if (numvertices <= 65536)
9611 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9612 for (i = 0;i < numtriangles*3;i++)
9613 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9616 // since we've copied everything, the batch now starts at 0
9617 rsurface.batchfirstvertex = 0;
9618 rsurface.batchnumvertices = batchnumvertices;
9619 rsurface.batchfirsttriangle = 0;
9620 rsurface.batchnumtriangles = batchnumtriangles;
9623 // apply skeletal animation that would have been done in the vertex shader
9624 if (rsurface.batchskeletaltransform3x4)
9626 const unsigned char *si;
9627 const unsigned char *sw;
9629 const float *b = rsurface.batchskeletaltransform3x4;
9630 float *vp, *vs, *vt, *vn;
9632 float m[3][4], n[3][4];
9633 float tp[3], ts[3], tt[3], tn[3];
9634 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9635 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9636 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9637 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9638 si = rsurface.batchskeletalindex4ub;
9639 sw = rsurface.batchskeletalweight4ub;
9640 vp = rsurface.batchvertex3f;
9641 vs = rsurface.batchsvector3f;
9642 vt = rsurface.batchtvector3f;
9643 vn = rsurface.batchnormal3f;
9644 memset(m[0], 0, sizeof(m));
9645 memset(n[0], 0, sizeof(n));
9646 for (i = 0;i < batchnumvertices;i++)
9648 t[0] = b + si[0]*12;
9651 // common case - only one matrix
9665 else if (sw[2] + sw[3])
9668 t[1] = b + si[1]*12;
9669 t[2] = b + si[2]*12;
9670 t[3] = b + si[3]*12;
9671 w[0] = sw[0] * (1.0f / 255.0f);
9672 w[1] = sw[1] * (1.0f / 255.0f);
9673 w[2] = sw[2] * (1.0f / 255.0f);
9674 w[3] = sw[3] * (1.0f / 255.0f);
9675 // blend the matrices
9676 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9677 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9678 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9679 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9680 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9681 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9682 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9683 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9684 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9685 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9686 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9687 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9692 t[1] = b + si[1]*12;
9693 w[0] = sw[0] * (1.0f / 255.0f);
9694 w[1] = sw[1] * (1.0f / 255.0f);
9695 // blend the matrices
9696 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9697 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9698 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9699 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9700 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9701 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9702 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9703 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9704 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9705 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9706 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9707 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9711 // modify the vertex
9713 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9714 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9715 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9719 // the normal transformation matrix is a set of cross products...
9720 CrossProduct(m[1], m[2], n[0]);
9721 CrossProduct(m[2], m[0], n[1]);
9722 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9724 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9725 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9726 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9727 VectorNormalize(vn);
9732 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9733 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9734 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9735 VectorNormalize(vs);
9738 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9739 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9740 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9741 VectorNormalize(vt);
9746 rsurface.batchskeletaltransform3x4 = NULL;
9747 rsurface.batchskeletalnumtransforms = 0;
9750 // q1bsp surfaces rendered in vertex color mode have to have colors
9751 // calculated based on lightstyles
9752 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9754 // generate color arrays for the surfaces in this list
9759 const unsigned char *lm;
9760 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9761 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9762 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9764 for (i = 0;i < texturenumsurfaces;i++)
9766 surface = texturesurfacelist[i];
9767 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9768 surfacenumvertices = surface->num_vertices;
9769 if (surface->lightmapinfo->samples)
9771 for (j = 0;j < surfacenumvertices;j++)
9773 lm = surface->lightmapinfo->samples + offsets[j];
9774 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9775 VectorScale(lm, scale, c);
9776 if (surface->lightmapinfo->styles[1] != 255)
9778 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9780 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9781 VectorMA(c, scale, lm, c);
9782 if (surface->lightmapinfo->styles[2] != 255)
9785 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9786 VectorMA(c, scale, lm, c);
9787 if (surface->lightmapinfo->styles[3] != 255)
9790 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9791 VectorMA(c, scale, lm, c);
9798 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);
9804 for (j = 0;j < surfacenumvertices;j++)
9806 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9813 // if vertices are deformed (sprite flares and things in maps, possibly
9814 // water waves, bulges and other deformations), modify the copied vertices
9816 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9818 switch (deform->deform)
9821 case Q3DEFORM_PROJECTIONSHADOW:
9822 case Q3DEFORM_TEXT0:
9823 case Q3DEFORM_TEXT1:
9824 case Q3DEFORM_TEXT2:
9825 case Q3DEFORM_TEXT3:
9826 case Q3DEFORM_TEXT4:
9827 case Q3DEFORM_TEXT5:
9828 case Q3DEFORM_TEXT6:
9829 case Q3DEFORM_TEXT7:
9832 case Q3DEFORM_AUTOSPRITE:
9833 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9834 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9835 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9836 VectorNormalize(newforward);
9837 VectorNormalize(newright);
9838 VectorNormalize(newup);
9839 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9840 // rsurface.batchvertex3f_vertexbuffer = NULL;
9841 // rsurface.batchvertex3f_bufferoffset = 0;
9842 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9843 // rsurface.batchsvector3f_vertexbuffer = NULL;
9844 // rsurface.batchsvector3f_bufferoffset = 0;
9845 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9846 // rsurface.batchtvector3f_vertexbuffer = NULL;
9847 // rsurface.batchtvector3f_bufferoffset = 0;
9848 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9849 // rsurface.batchnormal3f_vertexbuffer = NULL;
9850 // rsurface.batchnormal3f_bufferoffset = 0;
9851 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9852 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9853 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9854 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9855 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);
9856 // a single autosprite surface can contain multiple sprites...
9857 for (j = 0;j < batchnumvertices - 3;j += 4)
9859 VectorClear(center);
9860 for (i = 0;i < 4;i++)
9861 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9862 VectorScale(center, 0.25f, center);
9863 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9864 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9865 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9866 for (i = 0;i < 4;i++)
9868 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9869 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9872 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9873 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9874 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);
9876 case Q3DEFORM_AUTOSPRITE2:
9877 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9878 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9879 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9880 VectorNormalize(newforward);
9881 VectorNormalize(newright);
9882 VectorNormalize(newup);
9883 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9884 // rsurface.batchvertex3f_vertexbuffer = NULL;
9885 // rsurface.batchvertex3f_bufferoffset = 0;
9887 const float *v1, *v2;
9897 memset(shortest, 0, sizeof(shortest));
9898 // a single autosprite surface can contain multiple sprites...
9899 for (j = 0;j < batchnumvertices - 3;j += 4)
9901 VectorClear(center);
9902 for (i = 0;i < 4;i++)
9903 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9904 VectorScale(center, 0.25f, center);
9905 // find the two shortest edges, then use them to define the
9906 // axis vectors for rotating around the central axis
9907 for (i = 0;i < 6;i++)
9909 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9910 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9911 l = VectorDistance2(v1, v2);
9912 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9914 l += (1.0f / 1024.0f);
9915 if (shortest[0].length2 > l || i == 0)
9917 shortest[1] = shortest[0];
9918 shortest[0].length2 = l;
9919 shortest[0].v1 = v1;
9920 shortest[0].v2 = v2;
9922 else if (shortest[1].length2 > l || i == 1)
9924 shortest[1].length2 = l;
9925 shortest[1].v1 = v1;
9926 shortest[1].v2 = v2;
9929 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9930 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9931 // this calculates the right vector from the shortest edge
9932 // and the up vector from the edge midpoints
9933 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9934 VectorNormalize(right);
9935 VectorSubtract(end, start, up);
9936 VectorNormalize(up);
9937 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9938 VectorSubtract(rsurface.localvieworigin, center, forward);
9939 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9940 VectorNegate(forward, forward);
9941 VectorReflect(forward, 0, up, forward);
9942 VectorNormalize(forward);
9943 CrossProduct(up, forward, newright);
9944 VectorNormalize(newright);
9945 // rotate the quad around the up axis vector, this is made
9946 // especially easy by the fact we know the quad is flat,
9947 // so we only have to subtract the center position and
9948 // measure distance along the right vector, and then
9949 // multiply that by the newright vector and add back the
9951 // we also need to subtract the old position to undo the
9952 // displacement from the center, which we do with a
9953 // DotProduct, the subtraction/addition of center is also
9954 // optimized into DotProducts here
9955 l = DotProduct(right, center);
9956 for (i = 0;i < 4;i++)
9958 v1 = rsurface.batchvertex3f + 3*(j+i);
9959 f = DotProduct(right, v1) - l;
9960 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9964 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9966 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9967 // rsurface.batchnormal3f_vertexbuffer = NULL;
9968 // rsurface.batchnormal3f_bufferoffset = 0;
9969 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9971 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9973 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9974 // rsurface.batchsvector3f_vertexbuffer = NULL;
9975 // rsurface.batchsvector3f_bufferoffset = 0;
9976 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9977 // rsurface.batchtvector3f_vertexbuffer = NULL;
9978 // rsurface.batchtvector3f_bufferoffset = 0;
9979 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);
9982 case Q3DEFORM_NORMAL:
9983 // deform the normals to make reflections wavey
9984 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9985 rsurface.batchnormal3f_vertexbuffer = NULL;
9986 rsurface.batchnormal3f_bufferoffset = 0;
9987 for (j = 0;j < batchnumvertices;j++)
9990 float *normal = rsurface.batchnormal3f + 3*j;
9991 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9992 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9993 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9994 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9995 VectorNormalize(normal);
9997 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9999 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10000 // rsurface.batchsvector3f_vertexbuffer = NULL;
10001 // rsurface.batchsvector3f_bufferoffset = 0;
10002 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10003 // rsurface.batchtvector3f_vertexbuffer = NULL;
10004 // rsurface.batchtvector3f_bufferoffset = 0;
10005 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);
10008 case Q3DEFORM_WAVE:
10009 // deform vertex array to make wavey water and flags and such
10010 waveparms[0] = deform->waveparms[0];
10011 waveparms[1] = deform->waveparms[1];
10012 waveparms[2] = deform->waveparms[2];
10013 waveparms[3] = deform->waveparms[3];
10014 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10015 break; // if wavefunc is a nop, don't make a dynamic vertex array
10016 // this is how a divisor of vertex influence on deformation
10017 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10018 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10019 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10020 // rsurface.batchvertex3f_vertexbuffer = NULL;
10021 // rsurface.batchvertex3f_bufferoffset = 0;
10022 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10023 // rsurface.batchnormal3f_vertexbuffer = NULL;
10024 // rsurface.batchnormal3f_bufferoffset = 0;
10025 for (j = 0;j < batchnumvertices;j++)
10027 // if the wavefunc depends on time, evaluate it per-vertex
10030 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10031 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10033 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10035 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10036 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10037 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10039 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10040 // rsurface.batchsvector3f_vertexbuffer = NULL;
10041 // rsurface.batchsvector3f_bufferoffset = 0;
10042 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10043 // rsurface.batchtvector3f_vertexbuffer = NULL;
10044 // rsurface.batchtvector3f_bufferoffset = 0;
10045 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);
10048 case Q3DEFORM_BULGE:
10049 // deform vertex array to make the surface have moving bulges
10050 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10051 // rsurface.batchvertex3f_vertexbuffer = NULL;
10052 // rsurface.batchvertex3f_bufferoffset = 0;
10053 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10054 // rsurface.batchnormal3f_vertexbuffer = NULL;
10055 // rsurface.batchnormal3f_bufferoffset = 0;
10056 for (j = 0;j < batchnumvertices;j++)
10058 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10059 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10061 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10062 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10063 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10065 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10066 // rsurface.batchsvector3f_vertexbuffer = NULL;
10067 // rsurface.batchsvector3f_bufferoffset = 0;
10068 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10069 // rsurface.batchtvector3f_vertexbuffer = NULL;
10070 // rsurface.batchtvector3f_bufferoffset = 0;
10071 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);
10074 case Q3DEFORM_MOVE:
10075 // deform vertex array
10076 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10077 break; // if wavefunc is a nop, don't make a dynamic vertex array
10078 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10079 VectorScale(deform->parms, scale, waveparms);
10080 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10081 // rsurface.batchvertex3f_vertexbuffer = NULL;
10082 // rsurface.batchvertex3f_bufferoffset = 0;
10083 for (j = 0;j < batchnumvertices;j++)
10084 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10089 // generate texcoords based on the chosen texcoord source
10090 switch(rsurface.texture->tcgen.tcgen)
10093 case Q3TCGEN_TEXTURE:
10095 case Q3TCGEN_LIGHTMAP:
10096 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10097 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10098 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10099 if (rsurface.batchtexcoordlightmap2f)
10100 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10102 case Q3TCGEN_VECTOR:
10103 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10104 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10105 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10106 for (j = 0;j < batchnumvertices;j++)
10108 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10109 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10112 case Q3TCGEN_ENVIRONMENT:
10113 // make environment reflections using a spheremap
10114 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10115 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10116 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10117 for (j = 0;j < batchnumvertices;j++)
10119 // identical to Q3A's method, but executed in worldspace so
10120 // carried models can be shiny too
10122 float viewer[3], d, reflected[3], worldreflected[3];
10124 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10125 // VectorNormalize(viewer);
10127 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10129 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10130 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10131 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10132 // note: this is proportinal to viewer, so we can normalize later
10134 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10135 VectorNormalize(worldreflected);
10137 // note: this sphere map only uses world x and z!
10138 // so positive and negative y will LOOK THE SAME.
10139 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10140 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10144 // the only tcmod that needs software vertex processing is turbulent, so
10145 // check for it here and apply the changes if needed
10146 // and we only support that as the first one
10147 // (handling a mixture of turbulent and other tcmods would be problematic
10148 // without punting it entirely to a software path)
10149 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10151 amplitude = rsurface.texture->tcmods[0].parms[1];
10152 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10153 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10154 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10155 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10156 for (j = 0;j < batchnumvertices;j++)
10158 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);
10159 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10163 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10165 // convert the modified arrays to vertex structs
10166 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10167 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10168 // rsurface.batchvertexmesh_bufferoffset = 0;
10169 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10170 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10171 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10172 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10173 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10174 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10175 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10177 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10179 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10180 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10183 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10184 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10185 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10186 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10187 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10188 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10189 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10190 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10191 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10192 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10194 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10196 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10197 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10202 // upload buffer data for the dynamic batch
10203 if (vid.forcevbo || (r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object))
10205 if (rsurface.batchvertexmesh)
10206 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset, !vid.forcevbo);
10209 if (rsurface.batchvertex3f)
10210 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset, !vid.forcevbo);
10211 if (rsurface.batchsvector3f)
10212 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset, !vid.forcevbo);
10213 if (rsurface.batchtvector3f)
10214 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset, !vid.forcevbo);
10215 if (rsurface.batchnormal3f)
10216 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset, !vid.forcevbo);
10217 if (rsurface.batchlightmapcolor4f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10218 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset, !vid.forcevbo);
10219 if (rsurface.batchtexcoordtexture2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10220 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset, !vid.forcevbo);
10221 if (rsurface.batchtexcoordlightmap2f && r_batch_dynamicbuffer.integer && vid.support.arb_vertex_buffer_object)
10222 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset, !vid.forcevbo);
10223 if (rsurface.batchskeletalindex4ub)
10224 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset, !vid.forcevbo);
10225 if (rsurface.batchskeletalweight4ub)
10226 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset, !vid.forcevbo);
10228 if (rsurface.batchelement3s)
10229 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset, !vid.forcevbo);
10230 else if (rsurface.batchelement3i)
10231 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset, !vid.forcevbo);
10235 void RSurf_DrawBatch(void)
10237 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10238 // through the pipeline, killing it earlier in the pipeline would have
10239 // per-surface overhead rather than per-batch overhead, so it's best to
10240 // reject it here, before it hits glDraw.
10241 if (rsurface.batchnumtriangles == 0)
10244 // batch debugging code
10245 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10251 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10252 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10255 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10257 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10259 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10260 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);
10267 if (rsurface.batchmultidraw)
10269 // issue multiple draws rather than copying index data
10270 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10271 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10272 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10273 for (i = 0;i < numsurfaces;)
10275 // combine consecutive surfaces as one draw
10276 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10277 if (surfacelist[j] != surfacelist[k] + 1)
10279 firstvertex = surfacelist[i]->num_firstvertex;
10280 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10281 firsttriangle = surfacelist[i]->num_firsttriangle;
10282 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10283 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);
10289 // there is only one consecutive run of index data (may have been combined)
10290 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);
10294 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10296 // pick the closest matching water plane
10297 int planeindex, vertexindex, bestplaneindex = -1;
10301 r_waterstate_waterplane_t *p;
10302 qboolean prepared = false;
10304 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10306 if(p->camera_entity != rsurface.texture->camera_entity)
10311 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10313 if(rsurface.batchnumvertices == 0)
10316 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10318 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10319 d += fabs(PlaneDiff(vert, &p->plane));
10321 if (bestd > d || bestplaneindex < 0)
10324 bestplaneindex = planeindex;
10327 return bestplaneindex;
10328 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10329 // this situation though, as it might be better to render single larger
10330 // batches with useless stuff (backface culled for example) than to
10331 // render multiple smaller batches
10334 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10337 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10338 rsurface.passcolor4f_vertexbuffer = 0;
10339 rsurface.passcolor4f_bufferoffset = 0;
10340 for (i = 0;i < rsurface.batchnumvertices;i++)
10341 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10344 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10351 if (rsurface.passcolor4f)
10353 // generate color arrays
10354 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10355 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10356 rsurface.passcolor4f_vertexbuffer = 0;
10357 rsurface.passcolor4f_bufferoffset = 0;
10358 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)
10360 f = RSurf_FogVertex(v);
10369 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10370 rsurface.passcolor4f_vertexbuffer = 0;
10371 rsurface.passcolor4f_bufferoffset = 0;
10372 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10374 f = RSurf_FogVertex(v);
10383 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10390 if (!rsurface.passcolor4f)
10392 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10393 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10394 rsurface.passcolor4f_vertexbuffer = 0;
10395 rsurface.passcolor4f_bufferoffset = 0;
10396 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)
10398 f = RSurf_FogVertex(v);
10399 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10400 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10401 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10406 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10411 if (!rsurface.passcolor4f)
10413 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10414 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10415 rsurface.passcolor4f_vertexbuffer = 0;
10416 rsurface.passcolor4f_bufferoffset = 0;
10417 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10426 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10431 if (!rsurface.passcolor4f)
10433 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10434 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10435 rsurface.passcolor4f_vertexbuffer = 0;
10436 rsurface.passcolor4f_bufferoffset = 0;
10437 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10439 c2[0] = c[0] + r_refdef.scene.ambient;
10440 c2[1] = c[1] + r_refdef.scene.ambient;
10441 c2[2] = c[2] + r_refdef.scene.ambient;
10446 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10449 rsurface.passcolor4f = NULL;
10450 rsurface.passcolor4f_vertexbuffer = 0;
10451 rsurface.passcolor4f_bufferoffset = 0;
10452 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10453 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10454 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10455 GL_Color(r, g, b, a);
10456 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10457 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10458 R_Mesh_TexMatrix(0, NULL);
10462 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10464 // TODO: optimize applyfog && applycolor case
10465 // just apply fog if necessary, and tint the fog color array if necessary
10466 rsurface.passcolor4f = NULL;
10467 rsurface.passcolor4f_vertexbuffer = 0;
10468 rsurface.passcolor4f_bufferoffset = 0;
10469 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10470 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10471 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10472 GL_Color(r, g, b, a);
10476 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10479 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10480 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10481 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10482 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10483 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10484 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10485 GL_Color(r, g, b, a);
10489 static void RSurf_DrawBatch_GL11_ClampColor(void)
10494 if (!rsurface.passcolor4f)
10496 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10498 c2[0] = bound(0.0f, c1[0], 1.0f);
10499 c2[1] = bound(0.0f, c1[1], 1.0f);
10500 c2[2] = bound(0.0f, c1[2], 1.0f);
10501 c2[3] = bound(0.0f, c1[3], 1.0f);
10505 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10515 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10516 rsurface.passcolor4f_vertexbuffer = 0;
10517 rsurface.passcolor4f_bufferoffset = 0;
10518 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)
10520 f = -DotProduct(r_refdef.view.forward, n);
10522 f = f * 0.85 + 0.15; // work around so stuff won't get black
10523 f *= r_refdef.lightmapintensity;
10524 Vector4Set(c, f, f, f, 1);
10528 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10530 RSurf_DrawBatch_GL11_ApplyFakeLight();
10531 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10532 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10533 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10534 GL_Color(r, g, b, a);
10538 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10546 vec3_t ambientcolor;
10547 vec3_t diffusecolor;
10551 VectorCopy(rsurface.modellight_lightdir, lightdir);
10552 f = 0.5f * r_refdef.lightmapintensity;
10553 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10554 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10555 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10556 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10557 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10558 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10560 if (VectorLength2(diffusecolor) > 0)
10562 // q3-style directional shading
10563 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10564 rsurface.passcolor4f_vertexbuffer = 0;
10565 rsurface.passcolor4f_bufferoffset = 0;
10566 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)
10568 if ((f = DotProduct(n, lightdir)) > 0)
10569 VectorMA(ambientcolor, f, diffusecolor, c);
10571 VectorCopy(ambientcolor, c);
10578 *applycolor = false;
10582 *r = ambientcolor[0];
10583 *g = ambientcolor[1];
10584 *b = ambientcolor[2];
10585 rsurface.passcolor4f = NULL;
10586 rsurface.passcolor4f_vertexbuffer = 0;
10587 rsurface.passcolor4f_bufferoffset = 0;
10591 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10593 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10594 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10595 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10596 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10597 GL_Color(r, g, b, a);
10601 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10609 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10610 rsurface.passcolor4f_vertexbuffer = 0;
10611 rsurface.passcolor4f_bufferoffset = 0;
10613 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10615 f = 1 - RSurf_FogVertex(v);
10623 void RSurf_SetupDepthAndCulling(void)
10625 // submodels are biased to avoid z-fighting with world surfaces that they
10626 // may be exactly overlapping (avoids z-fighting artifacts on certain
10627 // doors and things in Quake maps)
10628 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10629 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10630 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10631 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10634 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10636 // transparent sky would be ridiculous
10637 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10639 R_SetupShader_Generic_NoTexture(false, false);
10640 skyrenderlater = true;
10641 RSurf_SetupDepthAndCulling();
10642 GL_DepthMask(true);
10643 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10644 // skymasking on them, and Quake3 never did sky masking (unlike
10645 // software Quake and software Quake2), so disable the sky masking
10646 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10647 // and skymasking also looks very bad when noclipping outside the
10648 // level, so don't use it then either.
10649 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10651 R_Mesh_ResetTextureState();
10652 if (skyrendermasked)
10654 R_SetupShader_DepthOrShadow(false, false, false);
10655 // depth-only (masking)
10656 GL_ColorMask(0,0,0,0);
10657 // just to make sure that braindead drivers don't draw
10658 // anything despite that colormask...
10659 GL_BlendFunc(GL_ZERO, GL_ONE);
10660 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10661 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10665 R_SetupShader_Generic_NoTexture(false, false);
10667 GL_BlendFunc(GL_ONE, GL_ZERO);
10668 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10669 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10670 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10673 if (skyrendermasked)
10674 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10676 R_Mesh_ResetTextureState();
10677 GL_Color(1, 1, 1, 1);
10680 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10681 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10682 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10684 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10688 // render screenspace normalmap to texture
10689 GL_DepthMask(true);
10690 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10695 // bind lightmap texture
10697 // water/refraction/reflection/camera surfaces have to be handled specially
10698 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10700 int start, end, startplaneindex;
10701 for (start = 0;start < texturenumsurfaces;start = end)
10703 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10704 if(startplaneindex < 0)
10706 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10707 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10711 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10713 // now that we have a batch using the same planeindex, render it
10714 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10716 // render water or distortion background
10717 GL_DepthMask(true);
10718 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);
10720 // blend surface on top
10721 GL_DepthMask(false);
10722 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10725 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10727 // render surface with reflection texture as input
10728 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10729 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);
10736 // render surface batch normally
10737 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10738 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);
10742 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10744 // OpenGL 1.3 path - anything not completely ancient
10745 qboolean applycolor;
10748 const texturelayer_t *layer;
10749 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);
10750 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10752 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10755 int layertexrgbscale;
10756 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10758 if (layerindex == 0)
10759 GL_AlphaTest(true);
10762 GL_AlphaTest(false);
10763 GL_DepthFunc(GL_EQUAL);
10766 GL_DepthMask(layer->depthmask && writedepth);
10767 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10768 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10770 layertexrgbscale = 4;
10771 VectorScale(layer->color, 0.25f, layercolor);
10773 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10775 layertexrgbscale = 2;
10776 VectorScale(layer->color, 0.5f, layercolor);
10780 layertexrgbscale = 1;
10781 VectorScale(layer->color, 1.0f, layercolor);
10783 layercolor[3] = layer->color[3];
10784 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10785 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10786 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10787 switch (layer->type)
10789 case TEXTURELAYERTYPE_LITTEXTURE:
10790 // single-pass lightmapped texture with 2x rgbscale
10791 R_Mesh_TexBind(0, r_texture_white);
10792 R_Mesh_TexMatrix(0, NULL);
10793 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10794 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10795 R_Mesh_TexBind(1, layer->texture);
10796 R_Mesh_TexMatrix(1, &layer->texmatrix);
10797 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10798 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10799 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10800 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10801 else if (FAKELIGHT_ENABLED)
10802 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10803 else if (rsurface.uselightmaptexture)
10804 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10806 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10808 case TEXTURELAYERTYPE_TEXTURE:
10809 // singletexture unlit texture with transparency support
10810 R_Mesh_TexBind(0, layer->texture);
10811 R_Mesh_TexMatrix(0, &layer->texmatrix);
10812 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10813 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10814 R_Mesh_TexBind(1, 0);
10815 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10816 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10818 case TEXTURELAYERTYPE_FOG:
10819 // singletexture fogging
10820 if (layer->texture)
10822 R_Mesh_TexBind(0, layer->texture);
10823 R_Mesh_TexMatrix(0, &layer->texmatrix);
10824 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10825 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10829 R_Mesh_TexBind(0, 0);
10830 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10832 R_Mesh_TexBind(1, 0);
10833 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10834 // generate a color array for the fog pass
10835 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10836 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10840 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10843 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10845 GL_DepthFunc(GL_LEQUAL);
10846 GL_AlphaTest(false);
10850 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10852 // OpenGL 1.1 - crusty old voodoo path
10855 const texturelayer_t *layer;
10856 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);
10857 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10859 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10861 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10863 if (layerindex == 0)
10864 GL_AlphaTest(true);
10867 GL_AlphaTest(false);
10868 GL_DepthFunc(GL_EQUAL);
10871 GL_DepthMask(layer->depthmask && writedepth);
10872 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10873 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10874 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10875 switch (layer->type)
10877 case TEXTURELAYERTYPE_LITTEXTURE:
10878 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10880 // two-pass lit texture with 2x rgbscale
10881 // first the lightmap pass
10882 R_Mesh_TexBind(0, r_texture_white);
10883 R_Mesh_TexMatrix(0, NULL);
10884 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10885 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10886 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10887 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10888 else if (FAKELIGHT_ENABLED)
10889 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10890 else if (rsurface.uselightmaptexture)
10891 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10893 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10894 // then apply the texture to it
10895 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10896 R_Mesh_TexBind(0, layer->texture);
10897 R_Mesh_TexMatrix(0, &layer->texmatrix);
10898 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10899 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10900 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);
10904 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10905 R_Mesh_TexBind(0, layer->texture);
10906 R_Mesh_TexMatrix(0, &layer->texmatrix);
10907 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10908 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10909 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10910 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);
10911 else if (FAKELIGHT_ENABLED)
10912 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);
10914 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);
10917 case TEXTURELAYERTYPE_TEXTURE:
10918 // singletexture unlit texture with transparency support
10919 R_Mesh_TexBind(0, layer->texture);
10920 R_Mesh_TexMatrix(0, &layer->texmatrix);
10921 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10922 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10923 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);
10925 case TEXTURELAYERTYPE_FOG:
10926 // singletexture fogging
10927 if (layer->texture)
10929 R_Mesh_TexBind(0, layer->texture);
10930 R_Mesh_TexMatrix(0, &layer->texmatrix);
10931 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10932 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10936 R_Mesh_TexBind(0, 0);
10937 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10939 // generate a color array for the fog pass
10940 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10941 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10945 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10948 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10950 GL_DepthFunc(GL_LEQUAL);
10951 GL_AlphaTest(false);
10955 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10959 r_vertexgeneric_t *batchvertex;
10962 // R_Mesh_ResetTextureState();
10963 R_SetupShader_Generic_NoTexture(false, false);
10965 if(rsurface.texture && rsurface.texture->currentskinframe)
10967 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10968 c[3] *= rsurface.texture->currentalpha;
10978 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10980 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10981 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10982 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10985 // brighten it up (as texture value 127 means "unlit")
10986 c[0] *= 2 * r_refdef.view.colorscale;
10987 c[1] *= 2 * r_refdef.view.colorscale;
10988 c[2] *= 2 * r_refdef.view.colorscale;
10990 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10991 c[3] *= r_wateralpha.value;
10993 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10995 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10996 GL_DepthMask(false);
10998 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11000 GL_BlendFunc(GL_ONE, GL_ONE);
11001 GL_DepthMask(false);
11003 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11005 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11006 GL_DepthMask(false);
11008 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11010 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11011 GL_DepthMask(false);
11015 GL_BlendFunc(GL_ONE, GL_ZERO);
11016 GL_DepthMask(writedepth);
11019 if (r_showsurfaces.integer == 3)
11021 rsurface.passcolor4f = NULL;
11023 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11025 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11027 rsurface.passcolor4f = NULL;
11028 rsurface.passcolor4f_vertexbuffer = 0;
11029 rsurface.passcolor4f_bufferoffset = 0;
11031 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11033 qboolean applycolor = true;
11036 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11038 r_refdef.lightmapintensity = 1;
11039 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11040 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11042 else if (FAKELIGHT_ENABLED)
11044 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11046 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11047 RSurf_DrawBatch_GL11_ApplyFakeLight();
11048 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11052 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11054 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11055 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11056 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11059 if(!rsurface.passcolor4f)
11060 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11062 RSurf_DrawBatch_GL11_ApplyAmbient();
11063 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11064 if(r_refdef.fogenabled)
11065 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11066 RSurf_DrawBatch_GL11_ClampColor();
11068 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11069 R_SetupShader_Generic_NoTexture(false, false);
11072 else if (!r_refdef.view.showdebug)
11074 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11075 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11076 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11078 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11079 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11081 R_Mesh_PrepareVertices_Generic_Unlock();
11084 else if (r_showsurfaces.integer == 4)
11086 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11087 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11088 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11090 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11091 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11092 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11094 R_Mesh_PrepareVertices_Generic_Unlock();
11097 else if (r_showsurfaces.integer == 2)
11100 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11101 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11102 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11104 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11105 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11106 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11107 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11108 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11109 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11110 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11112 R_Mesh_PrepareVertices_Generic_Unlock();
11113 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11117 int texturesurfaceindex;
11119 const msurface_t *surface;
11120 float surfacecolor4f[4];
11121 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11122 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11124 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11126 surface = texturesurfacelist[texturesurfaceindex];
11127 k = (int)(((size_t)surface) / sizeof(msurface_t));
11128 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11129 for (j = 0;j < surface->num_vertices;j++)
11131 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11132 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11136 R_Mesh_PrepareVertices_Generic_Unlock();
11141 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11144 RSurf_SetupDepthAndCulling();
11145 if (r_showsurfaces.integer)
11147 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11150 switch (vid.renderpath)
11152 case RENDERPATH_GL20:
11153 case RENDERPATH_D3D9:
11154 case RENDERPATH_D3D10:
11155 case RENDERPATH_D3D11:
11156 case RENDERPATH_SOFT:
11157 case RENDERPATH_GLES2:
11158 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11160 case RENDERPATH_GL13:
11161 case RENDERPATH_GLES1:
11162 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11164 case RENDERPATH_GL11:
11165 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11171 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11174 RSurf_SetupDepthAndCulling();
11175 if (r_showsurfaces.integer)
11177 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11180 switch (vid.renderpath)
11182 case RENDERPATH_GL20:
11183 case RENDERPATH_D3D9:
11184 case RENDERPATH_D3D10:
11185 case RENDERPATH_D3D11:
11186 case RENDERPATH_SOFT:
11187 case RENDERPATH_GLES2:
11188 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11190 case RENDERPATH_GL13:
11191 case RENDERPATH_GLES1:
11192 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11194 case RENDERPATH_GL11:
11195 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11201 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11204 int texturenumsurfaces, endsurface;
11205 texture_t *texture;
11206 const msurface_t *surface;
11207 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11209 // if the model is static it doesn't matter what value we give for
11210 // wantnormals and wanttangents, so this logic uses only rules applicable
11211 // to a model, knowing that they are meaningless otherwise
11212 if (ent == r_refdef.scene.worldentity)
11213 RSurf_ActiveWorldEntity();
11214 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11215 RSurf_ActiveModelEntity(ent, false, false, false);
11218 switch (vid.renderpath)
11220 case RENDERPATH_GL20:
11221 case RENDERPATH_D3D9:
11222 case RENDERPATH_D3D10:
11223 case RENDERPATH_D3D11:
11224 case RENDERPATH_SOFT:
11225 case RENDERPATH_GLES2:
11226 RSurf_ActiveModelEntity(ent, true, true, false);
11228 case RENDERPATH_GL11:
11229 case RENDERPATH_GL13:
11230 case RENDERPATH_GLES1:
11231 RSurf_ActiveModelEntity(ent, true, false, false);
11236 if (r_transparentdepthmasking.integer)
11238 qboolean setup = false;
11239 for (i = 0;i < numsurfaces;i = j)
11242 surface = rsurface.modelsurfaces + surfacelist[i];
11243 texture = surface->texture;
11244 rsurface.texture = R_GetCurrentTexture(texture);
11245 rsurface.lightmaptexture = NULL;
11246 rsurface.deluxemaptexture = NULL;
11247 rsurface.uselightmaptexture = false;
11248 // scan ahead until we find a different texture
11249 endsurface = min(i + 1024, numsurfaces);
11250 texturenumsurfaces = 0;
11251 texturesurfacelist[texturenumsurfaces++] = surface;
11252 for (;j < endsurface;j++)
11254 surface = rsurface.modelsurfaces + surfacelist[j];
11255 if (texture != surface->texture)
11257 texturesurfacelist[texturenumsurfaces++] = surface;
11259 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11261 // render the range of surfaces as depth
11265 GL_ColorMask(0,0,0,0);
11267 GL_DepthTest(true);
11268 GL_BlendFunc(GL_ONE, GL_ZERO);
11269 GL_DepthMask(true);
11270 // R_Mesh_ResetTextureState();
11272 RSurf_SetupDepthAndCulling();
11273 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11274 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11275 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11279 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11282 for (i = 0;i < numsurfaces;i = j)
11285 surface = rsurface.modelsurfaces + surfacelist[i];
11286 texture = surface->texture;
11287 rsurface.texture = R_GetCurrentTexture(texture);
11288 // scan ahead until we find a different texture
11289 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11290 texturenumsurfaces = 0;
11291 texturesurfacelist[texturenumsurfaces++] = surface;
11292 if(FAKELIGHT_ENABLED)
11294 rsurface.lightmaptexture = NULL;
11295 rsurface.deluxemaptexture = NULL;
11296 rsurface.uselightmaptexture = false;
11297 for (;j < endsurface;j++)
11299 surface = rsurface.modelsurfaces + surfacelist[j];
11300 if (texture != surface->texture)
11302 texturesurfacelist[texturenumsurfaces++] = surface;
11307 rsurface.lightmaptexture = surface->lightmaptexture;
11308 rsurface.deluxemaptexture = surface->deluxemaptexture;
11309 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11310 for (;j < endsurface;j++)
11312 surface = rsurface.modelsurfaces + surfacelist[j];
11313 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11315 texturesurfacelist[texturenumsurfaces++] = surface;
11318 // render the range of surfaces
11319 if (ent == r_refdef.scene.worldentity)
11320 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11322 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11324 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11327 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11329 // transparent surfaces get pushed off into the transparent queue
11330 int surfacelistindex;
11331 const msurface_t *surface;
11332 vec3_t tempcenter, center;
11333 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11335 surface = texturesurfacelist[surfacelistindex];
11336 if (r_transparent_sortsurfacesbynearest.integer)
11338 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11339 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11340 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11344 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11345 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11346 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11348 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11349 if (rsurface.entity->transparent_offset) // transparent offset
11351 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11352 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11353 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11355 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);
11359 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11361 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11363 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11365 RSurf_SetupDepthAndCulling();
11366 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11367 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11368 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11372 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11376 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11379 if (!rsurface.texture->currentnumlayers)
11381 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11382 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11384 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11386 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11387 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11388 else if (!rsurface.texture->currentnumlayers)
11390 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11392 // in the deferred case, transparent surfaces were queued during prepass
11393 if (!r_shadow_usingdeferredprepass)
11394 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11398 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11399 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11404 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11407 texture_t *texture;
11408 R_FrameData_SetMark();
11409 // break the surface list down into batches by texture and use of lightmapping
11410 for (i = 0;i < numsurfaces;i = j)
11413 // texture is the base texture pointer, rsurface.texture is the
11414 // current frame/skin the texture is directing us to use (for example
11415 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11416 // use skin 1 instead)
11417 texture = surfacelist[i]->texture;
11418 rsurface.texture = R_GetCurrentTexture(texture);
11419 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11421 // if this texture is not the kind we want, skip ahead to the next one
11422 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11426 if(FAKELIGHT_ENABLED || depthonly || prepass)
11428 rsurface.lightmaptexture = NULL;
11429 rsurface.deluxemaptexture = NULL;
11430 rsurface.uselightmaptexture = false;
11431 // simply scan ahead until we find a different texture or lightmap state
11432 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11437 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11438 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11439 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11440 // simply scan ahead until we find a different texture or lightmap state
11441 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11444 // render the range of surfaces
11445 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11447 R_FrameData_ReturnToMark();
11450 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11454 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11457 if (!rsurface.texture->currentnumlayers)
11459 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11460 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11462 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11464 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11465 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11466 else if (!rsurface.texture->currentnumlayers)
11468 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11470 // in the deferred case, transparent surfaces were queued during prepass
11471 if (!r_shadow_usingdeferredprepass)
11472 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11476 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11477 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11482 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11485 texture_t *texture;
11486 R_FrameData_SetMark();
11487 // break the surface list down into batches by texture and use of lightmapping
11488 for (i = 0;i < numsurfaces;i = j)
11491 // texture is the base texture pointer, rsurface.texture is the
11492 // current frame/skin the texture is directing us to use (for example
11493 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11494 // use skin 1 instead)
11495 texture = surfacelist[i]->texture;
11496 rsurface.texture = R_GetCurrentTexture(texture);
11497 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11499 // if this texture is not the kind we want, skip ahead to the next one
11500 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11504 if(FAKELIGHT_ENABLED || depthonly || prepass)
11506 rsurface.lightmaptexture = NULL;
11507 rsurface.deluxemaptexture = NULL;
11508 rsurface.uselightmaptexture = false;
11509 // simply scan ahead until we find a different texture or lightmap state
11510 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11515 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11516 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11517 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11518 // simply scan ahead until we find a different texture or lightmap state
11519 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11522 // render the range of surfaces
11523 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11525 R_FrameData_ReturnToMark();
11528 float locboxvertex3f[6*4*3] =
11530 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11531 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11532 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11533 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11534 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11535 1,0,0, 0,0,0, 0,1,0, 1,1,0
11538 unsigned short locboxelements[6*2*3] =
11543 12,13,14, 12,14,15,
11544 16,17,18, 16,18,19,
11548 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11551 cl_locnode_t *loc = (cl_locnode_t *)ent;
11553 float vertex3f[6*4*3];
11555 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11556 GL_DepthMask(false);
11557 GL_DepthRange(0, 1);
11558 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11559 GL_DepthTest(true);
11560 GL_CullFace(GL_NONE);
11561 R_EntityMatrix(&identitymatrix);
11563 // R_Mesh_ResetTextureState();
11565 i = surfacelist[0];
11566 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11567 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11568 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11569 surfacelist[0] < 0 ? 0.5f : 0.125f);
11571 if (VectorCompare(loc->mins, loc->maxs))
11573 VectorSet(size, 2, 2, 2);
11574 VectorMA(loc->mins, -0.5f, size, mins);
11578 VectorCopy(loc->mins, mins);
11579 VectorSubtract(loc->maxs, loc->mins, size);
11582 for (i = 0;i < 6*4*3;)
11583 for (j = 0;j < 3;j++, i++)
11584 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11586 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11587 R_SetupShader_Generic_NoTexture(false, false);
11588 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11591 void R_DrawLocs(void)
11594 cl_locnode_t *loc, *nearestloc;
11596 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11597 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11599 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11600 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11604 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11606 if (decalsystem->decals)
11607 Mem_Free(decalsystem->decals);
11608 memset(decalsystem, 0, sizeof(*decalsystem));
11611 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)
11614 tridecal_t *decals;
11617 // expand or initialize the system
11618 if (decalsystem->maxdecals <= decalsystem->numdecals)
11620 decalsystem_t old = *decalsystem;
11621 qboolean useshortelements;
11622 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11623 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11624 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)));
11625 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11626 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11627 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11628 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11629 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11630 if (decalsystem->numdecals)
11631 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11633 Mem_Free(old.decals);
11634 for (i = 0;i < decalsystem->maxdecals*3;i++)
11635 decalsystem->element3i[i] = i;
11636 if (useshortelements)
11637 for (i = 0;i < decalsystem->maxdecals*3;i++)
11638 decalsystem->element3s[i] = i;
11641 // grab a decal and search for another free slot for the next one
11642 decals = decalsystem->decals;
11643 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11644 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11646 decalsystem->freedecal = i;
11647 if (decalsystem->numdecals <= i)
11648 decalsystem->numdecals = i + 1;
11650 // initialize the decal
11652 decal->triangleindex = triangleindex;
11653 decal->surfaceindex = surfaceindex;
11654 decal->decalsequence = decalsequence;
11655 decal->color4f[0][0] = c0[0];
11656 decal->color4f[0][1] = c0[1];
11657 decal->color4f[0][2] = c0[2];
11658 decal->color4f[0][3] = 1;
11659 decal->color4f[1][0] = c1[0];
11660 decal->color4f[1][1] = c1[1];
11661 decal->color4f[1][2] = c1[2];
11662 decal->color4f[1][3] = 1;
11663 decal->color4f[2][0] = c2[0];
11664 decal->color4f[2][1] = c2[1];
11665 decal->color4f[2][2] = c2[2];
11666 decal->color4f[2][3] = 1;
11667 decal->vertex3f[0][0] = v0[0];
11668 decal->vertex3f[0][1] = v0[1];
11669 decal->vertex3f[0][2] = v0[2];
11670 decal->vertex3f[1][0] = v1[0];
11671 decal->vertex3f[1][1] = v1[1];
11672 decal->vertex3f[1][2] = v1[2];
11673 decal->vertex3f[2][0] = v2[0];
11674 decal->vertex3f[2][1] = v2[1];
11675 decal->vertex3f[2][2] = v2[2];
11676 decal->texcoord2f[0][0] = t0[0];
11677 decal->texcoord2f[0][1] = t0[1];
11678 decal->texcoord2f[1][0] = t1[0];
11679 decal->texcoord2f[1][1] = t1[1];
11680 decal->texcoord2f[2][0] = t2[0];
11681 decal->texcoord2f[2][1] = t2[1];
11682 TriangleNormal(v0, v1, v2, decal->plane);
11683 VectorNormalize(decal->plane);
11684 decal->plane[3] = DotProduct(v0, decal->plane);
11687 extern cvar_t cl_decals_bias;
11688 extern cvar_t cl_decals_models;
11689 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11690 // baseparms, parms, temps
11691 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)
11696 const float *vertex3f;
11697 const float *normal3f;
11699 float points[2][9][3];
11706 e = rsurface.modelelement3i + 3*triangleindex;
11708 vertex3f = rsurface.modelvertex3f;
11709 normal3f = rsurface.modelnormal3f;
11713 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11715 index = 3*e[cornerindex];
11716 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11721 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11723 index = 3*e[cornerindex];
11724 VectorCopy(vertex3f + index, v[cornerindex]);
11729 //TriangleNormal(v[0], v[1], v[2], normal);
11730 //if (DotProduct(normal, localnormal) < 0.0f)
11732 // clip by each of the box planes formed from the projection matrix
11733 // if anything survives, we emit the decal
11734 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]);
11737 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]);
11740 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]);
11743 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]);
11746 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]);
11749 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]);
11752 // some part of the triangle survived, so we have to accept it...
11755 // dynamic always uses the original triangle
11757 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11759 index = 3*e[cornerindex];
11760 VectorCopy(vertex3f + index, v[cornerindex]);
11763 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11765 // convert vertex positions to texcoords
11766 Matrix4x4_Transform(projection, v[cornerindex], temp);
11767 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11768 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11769 // calculate distance fade from the projection origin
11770 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11771 f = bound(0.0f, f, 1.0f);
11772 c[cornerindex][0] = r * f;
11773 c[cornerindex][1] = g * f;
11774 c[cornerindex][2] = b * f;
11775 c[cornerindex][3] = 1.0f;
11776 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11779 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);
11781 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11782 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);
11784 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)
11786 matrix4x4_t projection;
11787 decalsystem_t *decalsystem;
11790 const msurface_t *surface;
11791 const msurface_t *surfaces;
11792 const int *surfacelist;
11793 const texture_t *texture;
11795 int numsurfacelist;
11796 int surfacelistindex;
11799 float localorigin[3];
11800 float localnormal[3];
11801 float localmins[3];
11802 float localmaxs[3];
11805 float planes[6][4];
11808 int bih_triangles_count;
11809 int bih_triangles[256];
11810 int bih_surfaces[256];
11812 decalsystem = &ent->decalsystem;
11813 model = ent->model;
11814 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11816 R_DecalSystem_Reset(&ent->decalsystem);
11820 if (!model->brush.data_leafs && !cl_decals_models.integer)
11822 if (decalsystem->model)
11823 R_DecalSystem_Reset(decalsystem);
11827 if (decalsystem->model != model)
11828 R_DecalSystem_Reset(decalsystem);
11829 decalsystem->model = model;
11831 RSurf_ActiveModelEntity(ent, true, false, false);
11833 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11834 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11835 VectorNormalize(localnormal);
11836 localsize = worldsize*rsurface.inversematrixscale;
11837 localmins[0] = localorigin[0] - localsize;
11838 localmins[1] = localorigin[1] - localsize;
11839 localmins[2] = localorigin[2] - localsize;
11840 localmaxs[0] = localorigin[0] + localsize;
11841 localmaxs[1] = localorigin[1] + localsize;
11842 localmaxs[2] = localorigin[2] + localsize;
11844 //VectorCopy(localnormal, planes[4]);
11845 //VectorVectors(planes[4], planes[2], planes[0]);
11846 AnglesFromVectors(angles, localnormal, NULL, false);
11847 AngleVectors(angles, planes[0], planes[2], planes[4]);
11848 VectorNegate(planes[0], planes[1]);
11849 VectorNegate(planes[2], planes[3]);
11850 VectorNegate(planes[4], planes[5]);
11851 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11852 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11853 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11854 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11855 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11856 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11861 matrix4x4_t forwardprojection;
11862 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11863 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11868 float projectionvector[4][3];
11869 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11870 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11871 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11872 projectionvector[0][0] = planes[0][0] * ilocalsize;
11873 projectionvector[0][1] = planes[1][0] * ilocalsize;
11874 projectionvector[0][2] = planes[2][0] * ilocalsize;
11875 projectionvector[1][0] = planes[0][1] * ilocalsize;
11876 projectionvector[1][1] = planes[1][1] * ilocalsize;
11877 projectionvector[1][2] = planes[2][1] * ilocalsize;
11878 projectionvector[2][0] = planes[0][2] * ilocalsize;
11879 projectionvector[2][1] = planes[1][2] * ilocalsize;
11880 projectionvector[2][2] = planes[2][2] * ilocalsize;
11881 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11882 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11883 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11884 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11888 dynamic = model->surfmesh.isanimated;
11889 numsurfacelist = model->nummodelsurfaces;
11890 surfacelist = model->sortedmodelsurfaces;
11891 surfaces = model->data_surfaces;
11894 bih_triangles_count = -1;
11897 if(model->render_bih.numleafs)
11898 bih = &model->render_bih;
11899 else if(model->collision_bih.numleafs)
11900 bih = &model->collision_bih;
11903 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11904 if(bih_triangles_count == 0)
11906 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11908 if(bih_triangles_count > 0)
11910 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11912 surfaceindex = bih_surfaces[triangleindex];
11913 surface = surfaces + surfaceindex;
11914 texture = surface->texture;
11915 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11917 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11919 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11924 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11926 surfaceindex = surfacelist[surfacelistindex];
11927 surface = surfaces + surfaceindex;
11928 // check cull box first because it rejects more than any other check
11929 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11931 // skip transparent surfaces
11932 texture = surface->texture;
11933 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11935 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11937 numtriangles = surface->num_triangles;
11938 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11939 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11944 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11945 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)
11947 int renderentityindex;
11948 float worldmins[3];
11949 float worldmaxs[3];
11950 entity_render_t *ent;
11952 if (!cl_decals_newsystem.integer)
11955 worldmins[0] = worldorigin[0] - worldsize;
11956 worldmins[1] = worldorigin[1] - worldsize;
11957 worldmins[2] = worldorigin[2] - worldsize;
11958 worldmaxs[0] = worldorigin[0] + worldsize;
11959 worldmaxs[1] = worldorigin[1] + worldsize;
11960 worldmaxs[2] = worldorigin[2] + worldsize;
11962 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11964 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11966 ent = r_refdef.scene.entities[renderentityindex];
11967 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11970 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11974 typedef struct r_decalsystem_splatqueue_s
11976 vec3_t worldorigin;
11977 vec3_t worldnormal;
11983 r_decalsystem_splatqueue_t;
11985 int r_decalsystem_numqueued = 0;
11986 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11988 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)
11990 r_decalsystem_splatqueue_t *queue;
11992 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11995 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11996 VectorCopy(worldorigin, queue->worldorigin);
11997 VectorCopy(worldnormal, queue->worldnormal);
11998 Vector4Set(queue->color, r, g, b, a);
11999 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12000 queue->worldsize = worldsize;
12001 queue->decalsequence = cl.decalsequence++;
12004 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12007 r_decalsystem_splatqueue_t *queue;
12009 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12010 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);
12011 r_decalsystem_numqueued = 0;
12014 extern cvar_t cl_decals_max;
12015 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12018 decalsystem_t *decalsystem = &ent->decalsystem;
12025 if (!decalsystem->numdecals)
12028 if (r_showsurfaces.integer)
12031 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12033 R_DecalSystem_Reset(decalsystem);
12037 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12038 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12040 if (decalsystem->lastupdatetime)
12041 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12044 decalsystem->lastupdatetime = r_refdef.scene.time;
12045 numdecals = decalsystem->numdecals;
12047 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12049 if (decal->color4f[0][3])
12051 decal->lived += frametime;
12052 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12054 memset(decal, 0, sizeof(*decal));
12055 if (decalsystem->freedecal > i)
12056 decalsystem->freedecal = i;
12060 decal = decalsystem->decals;
12061 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12064 // collapse the array by shuffling the tail decals into the gaps
12067 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12068 decalsystem->freedecal++;
12069 if (decalsystem->freedecal == numdecals)
12071 decal[decalsystem->freedecal] = decal[--numdecals];
12074 decalsystem->numdecals = numdecals;
12076 if (numdecals <= 0)
12078 // if there are no decals left, reset decalsystem
12079 R_DecalSystem_Reset(decalsystem);
12083 extern skinframe_t *decalskinframe;
12084 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12087 decalsystem_t *decalsystem = &ent->decalsystem;
12096 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12099 numdecals = decalsystem->numdecals;
12103 if (r_showsurfaces.integer)
12106 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12108 R_DecalSystem_Reset(decalsystem);
12112 // if the model is static it doesn't matter what value we give for
12113 // wantnormals and wanttangents, so this logic uses only rules applicable
12114 // to a model, knowing that they are meaningless otherwise
12115 if (ent == r_refdef.scene.worldentity)
12116 RSurf_ActiveWorldEntity();
12118 RSurf_ActiveModelEntity(ent, false, false, false);
12120 decalsystem->lastupdatetime = r_refdef.scene.time;
12122 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12124 // update vertex positions for animated models
12125 v3f = decalsystem->vertex3f;
12126 c4f = decalsystem->color4f;
12127 t2f = decalsystem->texcoord2f;
12128 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12130 if (!decal->color4f[0][3])
12133 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12137 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12140 // update color values for fading decals
12141 if (decal->lived >= cl_decals_time.value)
12142 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12146 c4f[ 0] = decal->color4f[0][0] * alpha;
12147 c4f[ 1] = decal->color4f[0][1] * alpha;
12148 c4f[ 2] = decal->color4f[0][2] * alpha;
12150 c4f[ 4] = decal->color4f[1][0] * alpha;
12151 c4f[ 5] = decal->color4f[1][1] * alpha;
12152 c4f[ 6] = decal->color4f[1][2] * alpha;
12154 c4f[ 8] = decal->color4f[2][0] * alpha;
12155 c4f[ 9] = decal->color4f[2][1] * alpha;
12156 c4f[10] = decal->color4f[2][2] * alpha;
12159 t2f[0] = decal->texcoord2f[0][0];
12160 t2f[1] = decal->texcoord2f[0][1];
12161 t2f[2] = decal->texcoord2f[1][0];
12162 t2f[3] = decal->texcoord2f[1][1];
12163 t2f[4] = decal->texcoord2f[2][0];
12164 t2f[5] = decal->texcoord2f[2][1];
12166 // update vertex positions for animated models
12167 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12169 e = rsurface.modelelement3i + 3*decal->triangleindex;
12170 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12171 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12172 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12176 VectorCopy(decal->vertex3f[0], v3f);
12177 VectorCopy(decal->vertex3f[1], v3f + 3);
12178 VectorCopy(decal->vertex3f[2], v3f + 6);
12181 if (r_refdef.fogenabled)
12183 alpha = RSurf_FogVertex(v3f);
12184 VectorScale(c4f, alpha, c4f);
12185 alpha = RSurf_FogVertex(v3f + 3);
12186 VectorScale(c4f + 4, alpha, c4f + 4);
12187 alpha = RSurf_FogVertex(v3f + 6);
12188 VectorScale(c4f + 8, alpha, c4f + 8);
12199 r_refdef.stats[r_stat_drawndecals] += numtris;
12201 // now render the decals all at once
12202 // (this assumes they all use one particle font texture!)
12203 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);
12204 // R_Mesh_ResetTextureState();
12205 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12206 GL_DepthMask(false);
12207 GL_DepthRange(0, 1);
12208 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12209 GL_DepthTest(true);
12210 GL_CullFace(GL_NONE);
12211 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12212 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12213 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12217 static void R_DrawModelDecals(void)
12221 // fade faster when there are too many decals
12222 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12223 for (i = 0;i < r_refdef.scene.numentities;i++)
12224 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12226 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12227 for (i = 0;i < r_refdef.scene.numentities;i++)
12228 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12229 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12231 R_DecalSystem_ApplySplatEntitiesQueue();
12233 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12234 for (i = 0;i < r_refdef.scene.numentities;i++)
12235 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12237 r_refdef.stats[r_stat_totaldecals] += numdecals;
12239 if (r_showsurfaces.integer)
12242 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12244 for (i = 0;i < r_refdef.scene.numentities;i++)
12246 if (!r_refdef.viewcache.entityvisible[i])
12248 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12249 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12253 extern cvar_t mod_collision_bih;
12254 static void R_DrawDebugModel(void)
12256 entity_render_t *ent = rsurface.entity;
12257 int i, j, k, l, flagsmask;
12258 const msurface_t *surface;
12259 dp_model_t *model = ent->model;
12262 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12265 if (r_showoverdraw.value > 0)
12267 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12268 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12269 R_SetupShader_Generic_NoTexture(false, false);
12270 GL_DepthTest(false);
12271 GL_DepthMask(false);
12272 GL_DepthRange(0, 1);
12273 GL_BlendFunc(GL_ONE, GL_ONE);
12274 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12276 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12278 rsurface.texture = R_GetCurrentTexture(surface->texture);
12279 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12281 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12282 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12283 if (!rsurface.texture->currentlayers->depthmask)
12284 GL_Color(c, 0, 0, 1.0f);
12285 else if (ent == r_refdef.scene.worldentity)
12286 GL_Color(c, c, c, 1.0f);
12288 GL_Color(0, c, 0, 1.0f);
12289 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12293 rsurface.texture = NULL;
12296 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12298 // R_Mesh_ResetTextureState();
12299 R_SetupShader_Generic_NoTexture(false, false);
12300 GL_DepthRange(0, 1);
12301 GL_DepthTest(!r_showdisabledepthtest.integer);
12302 GL_DepthMask(false);
12303 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12305 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12309 qboolean cullbox = false;
12310 const q3mbrush_t *brush;
12311 const bih_t *bih = &model->collision_bih;
12312 const bih_leaf_t *bihleaf;
12313 float vertex3f[3][3];
12314 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12315 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12317 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12319 switch (bihleaf->type)
12322 brush = model->brush.data_brushes + bihleaf->itemindex;
12323 if (brush->colbrushf && brush->colbrushf->numtriangles)
12325 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);
12326 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12327 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12330 case BIH_COLLISIONTRIANGLE:
12331 triangleindex = bihleaf->itemindex;
12332 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12333 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12334 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12335 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);
12336 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12337 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12339 case BIH_RENDERTRIANGLE:
12340 triangleindex = bihleaf->itemindex;
12341 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12342 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12343 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12344 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);
12345 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12346 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12352 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12355 if (r_showtris.integer && qglPolygonMode)
12357 if (r_showdisabledepthtest.integer)
12359 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12360 GL_DepthMask(false);
12364 GL_BlendFunc(GL_ONE, GL_ZERO);
12365 GL_DepthMask(true);
12367 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12368 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12370 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12372 rsurface.texture = R_GetCurrentTexture(surface->texture);
12373 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12375 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12376 if (!rsurface.texture->currentlayers->depthmask)
12377 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12378 else if (ent == r_refdef.scene.worldentity)
12379 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12381 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12382 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12386 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12387 rsurface.texture = NULL;
12390 if (r_shownormals.value != 0 && qglBegin)
12392 if (r_showdisabledepthtest.integer)
12394 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12395 GL_DepthMask(false);
12399 GL_BlendFunc(GL_ONE, GL_ZERO);
12400 GL_DepthMask(true);
12402 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12404 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12406 rsurface.texture = R_GetCurrentTexture(surface->texture);
12407 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12409 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12410 qglBegin(GL_LINES);
12411 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12413 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12415 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12416 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12417 qglVertex3f(v[0], v[1], v[2]);
12418 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12419 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12420 qglVertex3f(v[0], v[1], v[2]);
12423 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12425 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12427 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12428 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12429 qglVertex3f(v[0], v[1], v[2]);
12430 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12431 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12432 qglVertex3f(v[0], v[1], v[2]);
12435 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12437 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12439 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12440 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12441 qglVertex3f(v[0], v[1], v[2]);
12442 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12443 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12444 qglVertex3f(v[0], v[1], v[2]);
12447 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12449 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12451 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12452 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12453 qglVertex3f(v[0], v[1], v[2]);
12454 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12455 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12456 qglVertex3f(v[0], v[1], v[2]);
12463 rsurface.texture = NULL;
12468 int r_maxsurfacelist = 0;
12469 const msurface_t **r_surfacelist = NULL;
12470 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12472 int i, j, endj, flagsmask;
12473 dp_model_t *model = r_refdef.scene.worldmodel;
12474 msurface_t *surfaces;
12475 unsigned char *update;
12476 int numsurfacelist = 0;
12480 if (r_maxsurfacelist < model->num_surfaces)
12482 r_maxsurfacelist = model->num_surfaces;
12484 Mem_Free((msurface_t**)r_surfacelist);
12485 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12488 RSurf_ActiveWorldEntity();
12490 surfaces = model->data_surfaces;
12491 update = model->brushq1.lightmapupdateflags;
12493 // update light styles on this submodel
12494 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12496 model_brush_lightstyleinfo_t *style;
12497 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12499 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12501 int *list = style->surfacelist;
12502 style->value = r_refdef.scene.lightstylevalue[style->style];
12503 for (j = 0;j < style->numsurfaces;j++)
12504 update[list[j]] = true;
12509 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12513 R_DrawDebugModel();
12514 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12518 rsurface.lightmaptexture = NULL;
12519 rsurface.deluxemaptexture = NULL;
12520 rsurface.uselightmaptexture = false;
12521 rsurface.texture = NULL;
12522 rsurface.rtlight = NULL;
12523 numsurfacelist = 0;
12524 // add visible surfaces to draw list
12525 for (i = 0;i < model->nummodelsurfaces;i++)
12527 j = model->sortedmodelsurfaces[i];
12528 if (r_refdef.viewcache.world_surfacevisible[j])
12529 r_surfacelist[numsurfacelist++] = surfaces + j;
12531 // update lightmaps if needed
12532 if (model->brushq1.firstrender)
12534 model->brushq1.firstrender = false;
12535 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12537 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12541 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12542 if (r_refdef.viewcache.world_surfacevisible[j])
12544 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12546 // don't do anything if there were no surfaces
12547 if (!numsurfacelist)
12549 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12552 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12554 // add to stats if desired
12555 if (r_speeds.integer && !skysurfaces && !depthonly)
12557 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12558 for (j = 0;j < numsurfacelist;j++)
12559 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12562 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12565 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12567 int i, j, endj, flagsmask;
12568 dp_model_t *model = ent->model;
12569 msurface_t *surfaces;
12570 unsigned char *update;
12571 int numsurfacelist = 0;
12575 if (r_maxsurfacelist < model->num_surfaces)
12577 r_maxsurfacelist = model->num_surfaces;
12579 Mem_Free((msurface_t **)r_surfacelist);
12580 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12583 // if the model is static it doesn't matter what value we give for
12584 // wantnormals and wanttangents, so this logic uses only rules applicable
12585 // to a model, knowing that they are meaningless otherwise
12586 if (ent == r_refdef.scene.worldentity)
12587 RSurf_ActiveWorldEntity();
12588 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12589 RSurf_ActiveModelEntity(ent, false, false, false);
12591 RSurf_ActiveModelEntity(ent, true, true, true);
12592 else if (depthonly)
12594 switch (vid.renderpath)
12596 case RENDERPATH_GL20:
12597 case RENDERPATH_D3D9:
12598 case RENDERPATH_D3D10:
12599 case RENDERPATH_D3D11:
12600 case RENDERPATH_SOFT:
12601 case RENDERPATH_GLES2:
12602 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12604 case RENDERPATH_GL11:
12605 case RENDERPATH_GL13:
12606 case RENDERPATH_GLES1:
12607 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12613 switch (vid.renderpath)
12615 case RENDERPATH_GL20:
12616 case RENDERPATH_D3D9:
12617 case RENDERPATH_D3D10:
12618 case RENDERPATH_D3D11:
12619 case RENDERPATH_SOFT:
12620 case RENDERPATH_GLES2:
12621 RSurf_ActiveModelEntity(ent, true, true, false);
12623 case RENDERPATH_GL11:
12624 case RENDERPATH_GL13:
12625 case RENDERPATH_GLES1:
12626 RSurf_ActiveModelEntity(ent, true, false, false);
12631 surfaces = model->data_surfaces;
12632 update = model->brushq1.lightmapupdateflags;
12634 // update light styles
12635 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12637 model_brush_lightstyleinfo_t *style;
12638 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12640 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12642 int *list = style->surfacelist;
12643 style->value = r_refdef.scene.lightstylevalue[style->style];
12644 for (j = 0;j < style->numsurfaces;j++)
12645 update[list[j]] = true;
12650 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12654 R_DrawDebugModel();
12655 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12659 rsurface.lightmaptexture = NULL;
12660 rsurface.deluxemaptexture = NULL;
12661 rsurface.uselightmaptexture = false;
12662 rsurface.texture = NULL;
12663 rsurface.rtlight = NULL;
12664 numsurfacelist = 0;
12665 // add visible surfaces to draw list
12666 for (i = 0;i < model->nummodelsurfaces;i++)
12667 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12668 // don't do anything if there were no surfaces
12669 if (!numsurfacelist)
12671 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12674 // update lightmaps if needed
12678 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12683 R_BuildLightMap(ent, surfaces + j);
12688 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12690 // add to stats if desired
12691 if (r_speeds.integer && !skysurfaces && !depthonly)
12693 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12694 for (j = 0;j < numsurfacelist;j++)
12695 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12698 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12701 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12703 static texture_t texture;
12704 static msurface_t surface;
12705 const msurface_t *surfacelist = &surface;
12707 // fake enough texture and surface state to render this geometry
12709 texture.update_lastrenderframe = -1; // regenerate this texture
12710 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12711 texture.currentskinframe = skinframe;
12712 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12713 texture.offsetmapping = OFFSETMAPPING_OFF;
12714 texture.offsetscale = 1;
12715 texture.specularscalemod = 1;
12716 texture.specularpowermod = 1;
12717 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12718 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12719 // JUST GREP FOR "specularscalemod = 1".
12721 surface.texture = &texture;
12722 surface.num_triangles = numtriangles;
12723 surface.num_firsttriangle = firsttriangle;
12724 surface.num_vertices = numvertices;
12725 surface.num_firstvertex = firstvertex;
12728 rsurface.texture = R_GetCurrentTexture(surface.texture);
12729 rsurface.lightmaptexture = NULL;
12730 rsurface.deluxemaptexture = NULL;
12731 rsurface.uselightmaptexture = false;
12732 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12735 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)
12737 static msurface_t surface;
12738 const msurface_t *surfacelist = &surface;
12740 // fake enough texture and surface state to render this geometry
12741 surface.texture = texture;
12742 surface.num_triangles = numtriangles;
12743 surface.num_firsttriangle = firsttriangle;
12744 surface.num_vertices = numvertices;
12745 surface.num_firstvertex = firstvertex;
12748 rsurface.texture = R_GetCurrentTexture(surface.texture);
12749 rsurface.lightmaptexture = NULL;
12750 rsurface.deluxemaptexture = NULL;
12751 rsurface.uselightmaptexture = false;
12752 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);