2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47 static qboolean r_gpuskeletal;
54 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
55 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
61 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
62 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
63 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
64 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
65 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
73 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
81 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
82 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
85 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
92 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
93 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
102 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
127 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
138 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
149 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
150 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
156 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
157 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
158 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
162 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
163 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
172 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
175 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
178 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
179 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
180 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
181 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
182 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
183 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
184 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
186 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
187 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
188 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
189 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
190 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
191 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
192 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
193 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
194 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
196 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
197 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
198 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
199 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
201 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
202 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
204 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
205 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
206 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
207 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
208 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
209 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
211 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
212 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
213 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
214 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
215 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
218 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
219 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
220 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
222 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
224 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
226 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
228 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
230 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
231 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
232 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
235 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
236 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
238 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
240 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
241 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
243 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
244 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
245 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
246 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
249 extern cvar_t v_glslgamma;
250 extern cvar_t v_glslgamma_2d;
252 extern qboolean v_flipped_state;
254 r_framebufferstate_t r_fb;
256 /// shadow volume bsp struct with automatically growing nodes buffer
259 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
290 typedef struct r_qwskincache_s
292 char name[MAX_QPATH];
293 skinframe_t *skinframe;
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
310 const float r_d3dscreenvertex3f[12] =
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
321 for (i = 0;i < verts;i++)
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
335 for (i = 0;i < verts;i++)
345 // FIXME: move this to client?
348 if (gamemode == GAME_NEHAHRA)
350 Cvar_Set("gl_fogenable", "0");
351 Cvar_Set("gl_fogdensity", "0.2");
352 Cvar_Set("gl_fogred", "0.3");
353 Cvar_Set("gl_foggreen", "0.3");
354 Cvar_Set("gl_fogblue", "0.3");
356 r_refdef.fog_density = 0;
357 r_refdef.fog_red = 0;
358 r_refdef.fog_green = 0;
359 r_refdef.fog_blue = 0;
360 r_refdef.fog_alpha = 1;
361 r_refdef.fog_start = 0;
362 r_refdef.fog_end = 16384;
363 r_refdef.fog_height = 1<<30;
364 r_refdef.fog_fadedepth = 128;
365 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
368 static void R_BuildBlankTextures(void)
370 unsigned char data[4];
371 data[2] = 128; // normal X
372 data[1] = 128; // normal Y
373 data[0] = 255; // normal Z
374 data[3] = 255; // height
375 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 static void R_BuildNoTexture(void)
396 unsigned char pix[16][16][4];
397 // this makes a light grey/dark grey checkerboard texture
398 for (y = 0;y < 16;y++)
400 for (x = 0;x < 16;x++)
402 if ((y < 8) ^ (x < 8))
418 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
421 static void R_BuildWhiteCube(void)
423 unsigned char data[6*1*1*4];
424 memset(data, 255, sizeof(data));
425 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
428 static void R_BuildNormalizationCube(void)
432 vec_t s, t, intensity;
435 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436 for (side = 0;side < 6;side++)
438 for (y = 0;y < NORMSIZE;y++)
440 for (x = 0;x < NORMSIZE;x++)
442 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
478 intensity = 127.0f / sqrt(DotProduct(v, v));
479 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482 data[((side*64+y)*64+x)*4+3] = 255;
486 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
490 static void R_BuildFogTexture(void)
494 unsigned char data1[FOGWIDTH][4];
495 //unsigned char data2[FOGWIDTH][4];
498 r_refdef.fogmasktable_start = r_refdef.fog_start;
499 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500 r_refdef.fogmasktable_range = r_refdef.fogrange;
501 r_refdef.fogmasktable_density = r_refdef.fog_density;
503 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506 d = (x * r - r_refdef.fogmasktable_start);
507 if(developer_extra.integer)
508 Con_DPrintf("%f ", d);
510 if (r_fog_exp2.integer)
511 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514 if(developer_extra.integer)
515 Con_DPrintf(" : %f ", alpha);
516 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517 if(developer_extra.integer)
518 Con_DPrintf(" = %f\n", alpha);
519 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
522 for (x = 0;x < FOGWIDTH;x++)
524 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529 //data2[x][0] = 255 - b;
530 //data2[x][1] = 255 - b;
531 //data2[x][2] = 255 - b;
534 if (r_texture_fogattenuation)
536 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
546 static void R_BuildFogHeightTexture(void)
548 unsigned char *inpixels;
556 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557 if (r_refdef.fogheighttexturename[0])
558 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
561 r_refdef.fog_height_tablesize = 0;
562 if (r_texture_fogheighttexture)
563 R_FreeTexture(r_texture_fogheighttexture);
564 r_texture_fogheighttexture = NULL;
565 if (r_refdef.fog_height_table2d)
566 Mem_Free(r_refdef.fog_height_table2d);
567 r_refdef.fog_height_table2d = NULL;
568 if (r_refdef.fog_height_table1d)
569 Mem_Free(r_refdef.fog_height_table1d);
570 r_refdef.fog_height_table1d = NULL;
574 r_refdef.fog_height_tablesize = size;
575 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579 // LordHavoc: now the magic - what is that table2d for? it is a cooked
580 // average fog color table accounting for every fog layer between a point
581 // and the camera. (Note: attenuation is handled separately!)
582 for (y = 0;y < size;y++)
584 for (x = 0;x < size;x++)
590 for (j = x;j <= y;j++)
592 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
598 for (j = x;j >= y;j--)
600 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
611 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
614 //=======================================================================================================================================================
616 static const char *builtinshaderstrings[] =
618 #include "shader_glsl.h"
622 const char *builtinhlslshaderstrings[] =
624 #include "shader_hlsl.h"
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
631 //=======================================================================================================================================================
633 typedef struct shaderpermutationinfo_s
638 shaderpermutationinfo_t;
640 typedef struct shadermodeinfo_s
642 const char *filename;
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {"#define USEDIFFUSE\n", " diffuse"},
652 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653 {"#define USEVIEWTINT\n", " viewtint"},
654 {"#define USECOLORMAPPING\n", " colormapping"},
655 {"#define USESATURATION\n", " saturation"},
656 {"#define USEFOGINSIDE\n", " foginside"},
657 {"#define USEFOGOUTSIDE\n", " fogoutside"},
658 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660 {"#define USEGAMMARAMPS\n", " gammaramps"},
661 {"#define USECUBEFILTER\n", " cubefilter"},
662 {"#define USEGLOW\n", " glow"},
663 {"#define USEBLOOM\n", " bloom"},
664 {"#define USESPECULAR\n", " specular"},
665 {"#define USEPOSTPROCESSING\n", " postprocessing"},
666 {"#define USEREFLECTION\n", " reflection"},
667 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
671 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673 {"#define USEALPHAKILL\n", " alphakill"},
674 {"#define USEREFLECTCUBE\n", " reflectcube"},
675 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676 {"#define USEBOUNCEGRID\n", " bouncegrid"},
677 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
678 {"#define USETRIPPY\n", " trippy"},
679 {"#define USEDEPTHRGB\n", " depthrgb"},
680 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
681 {"#define USESKELETAL\n", " skeletal"}
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
687 {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688 {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689 {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690 {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691 {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692 {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693 {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
697 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
698 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
699 {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
700 {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
701 {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
702 {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703 {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
708 {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709 {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710 {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711 {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712 {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713 {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714 {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720 {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721 {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722 {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723 {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724 {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
727 struct r_glsl_permutation_s;
728 typedef struct r_glsl_permutation_s
731 struct r_glsl_permutation_s *hashnext;
733 unsigned int permutation;
735 /// indicates if we have tried compiling this permutation already
737 /// 0 if compilation failed
739 // texture units assigned to each detected uniform
740 int tex_Texture_First;
741 int tex_Texture_Second;
742 int tex_Texture_GammaRamps;
743 int tex_Texture_Normal;
744 int tex_Texture_Color;
745 int tex_Texture_Gloss;
746 int tex_Texture_Glow;
747 int tex_Texture_SecondaryNormal;
748 int tex_Texture_SecondaryColor;
749 int tex_Texture_SecondaryGloss;
750 int tex_Texture_SecondaryGlow;
751 int tex_Texture_Pants;
752 int tex_Texture_Shirt;
753 int tex_Texture_FogHeightTexture;
754 int tex_Texture_FogMask;
755 int tex_Texture_Lightmap;
756 int tex_Texture_Deluxemap;
757 int tex_Texture_Attenuation;
758 int tex_Texture_Cube;
759 int tex_Texture_Refraction;
760 int tex_Texture_Reflection;
761 int tex_Texture_ShadowMap2D;
762 int tex_Texture_CubeProjection;
763 int tex_Texture_ScreenNormalMap;
764 int tex_Texture_ScreenDiffuse;
765 int tex_Texture_ScreenSpecular;
766 int tex_Texture_ReflectMask;
767 int tex_Texture_ReflectCube;
768 int tex_Texture_BounceGrid;
769 /// locations of detected uniforms in program object, or -1 if not found
770 int loc_Texture_First;
771 int loc_Texture_Second;
772 int loc_Texture_GammaRamps;
773 int loc_Texture_Normal;
774 int loc_Texture_Color;
775 int loc_Texture_Gloss;
776 int loc_Texture_Glow;
777 int loc_Texture_SecondaryNormal;
778 int loc_Texture_SecondaryColor;
779 int loc_Texture_SecondaryGloss;
780 int loc_Texture_SecondaryGlow;
781 int loc_Texture_Pants;
782 int loc_Texture_Shirt;
783 int loc_Texture_FogHeightTexture;
784 int loc_Texture_FogMask;
785 int loc_Texture_Lightmap;
786 int loc_Texture_Deluxemap;
787 int loc_Texture_Attenuation;
788 int loc_Texture_Cube;
789 int loc_Texture_Refraction;
790 int loc_Texture_Reflection;
791 int loc_Texture_ShadowMap2D;
792 int loc_Texture_CubeProjection;
793 int loc_Texture_ScreenNormalMap;
794 int loc_Texture_ScreenDiffuse;
795 int loc_Texture_ScreenSpecular;
796 int loc_Texture_ReflectMask;
797 int loc_Texture_ReflectCube;
798 int loc_Texture_BounceGrid;
800 int loc_BloomBlur_Parameters;
802 int loc_Color_Ambient;
803 int loc_Color_Diffuse;
804 int loc_Color_Specular;
808 int loc_DeferredColor_Ambient;
809 int loc_DeferredColor_Diffuse;
810 int loc_DeferredColor_Specular;
811 int loc_DeferredMod_Diffuse;
812 int loc_DeferredMod_Specular;
813 int loc_DistortScaleRefractReflect;
816 int loc_FogHeightFade;
818 int loc_FogPlaneViewDist;
819 int loc_FogRangeRecip;
822 int loc_LightPosition;
823 int loc_OffsetMapping_ScaleSteps;
824 int loc_OffsetMapping_LodDistance;
825 int loc_OffsetMapping_Bias;
827 int loc_ReflectColor;
828 int loc_ReflectFactor;
829 int loc_ReflectOffset;
830 int loc_RefractColor;
832 int loc_ScreenCenterRefractReflect;
833 int loc_ScreenScaleRefractReflect;
834 int loc_ScreenToDepth;
835 int loc_ShadowMap_Parameters;
836 int loc_ShadowMap_TextureScale;
837 int loc_SpecularPower;
838 int loc_Skeletal_Transform12;
843 int loc_ViewTintColor;
845 int loc_ModelToLight;
847 int loc_BackgroundTexMatrix;
848 int loc_ModelViewProjectionMatrix;
849 int loc_ModelViewMatrix;
850 int loc_PixelToScreenTexCoord;
851 int loc_ModelToReflectCube;
852 int loc_ShadowMapMatrix;
853 int loc_BloomColorSubtract;
854 int loc_NormalmapScrollBlend;
855 int loc_BounceGridMatrix;
856 int loc_BounceGridIntensity;
857 /// uniform block bindings
858 int ubibind_Skeletal_Transform12_UniformBlock;
859 /// uniform block indices
860 int ubiloc_Skeletal_Transform12_UniformBlock;
862 r_glsl_permutation_t;
864 #define SHADERPERMUTATION_HASHSIZE 256
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
871 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
877 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
879 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
880 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
881 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
882 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
883 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
885 #define SHADERSTATICPARMS_COUNT 13
887 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
888 static int shaderstaticparms_count = 0;
890 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
891 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
893 extern qboolean r_shadow_shadowmapsampler;
894 extern int r_shadow_shadowmappcf;
895 qboolean R_CompileShader_CheckStaticParms(void)
897 static int r_compileshader_staticparms_save[1];
898 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
899 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
902 if (r_glsl_saturation_redcompensate.integer)
903 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
904 if (r_glsl_vertextextureblend_usebothalphas.integer)
905 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
906 if (r_shadow_glossexact.integer)
907 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
908 if (r_glsl_postprocess.integer)
910 if (r_glsl_postprocess_uservec1_enable.integer)
911 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
912 if (r_glsl_postprocess_uservec2_enable.integer)
913 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
914 if (r_glsl_postprocess_uservec3_enable.integer)
915 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
916 if (r_glsl_postprocess_uservec4_enable.integer)
917 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
919 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
920 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
922 if (r_shadow_shadowmapsampler)
923 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
924 if (r_shadow_shadowmappcf > 1)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
926 else if (r_shadow_shadowmappcf)
927 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
928 if (r_celshading.integer)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
930 if (r_celoutlines.integer)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
933 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
936 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
937 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
938 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
940 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
941 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
943 shaderstaticparms_count = 0;
946 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
947 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
948 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
949 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
950 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
951 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
952 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
953 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
954 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
955 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
956 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
957 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
958 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
961 /// information about each possible shader permutation
962 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
963 /// currently selected permutation
964 r_glsl_permutation_t *r_glsl_permutation;
965 /// storage for permutations linked in the hash table
966 memexpandablearray_t r_glsl_permutationarray;
968 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
970 //unsigned int hashdepth = 0;
971 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
972 r_glsl_permutation_t *p;
973 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
975 if (p->mode == mode && p->permutation == permutation)
977 //if (hashdepth > 10)
978 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
983 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
985 p->permutation = permutation;
986 p->hashnext = r_glsl_permutationhash[mode][hashindex];
987 r_glsl_permutationhash[mode][hashindex] = p;
988 //if (hashdepth > 10)
989 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
993 static char *R_ShaderStrCat(const char **strings)
996 const char **p = strings;
999 for (p = strings;(t = *p);p++)
1002 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1004 for (p = strings;(t = *p);p++)
1014 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1017 if (!filename || !filename[0])
1019 // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1020 if (!strcmp(filename, "glsl/default.glsl"))
1023 return R_ShaderStrCat(builtinshaderstrings);
1024 if (!glslshaderstring)
1026 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1027 if (glslshaderstring)
1028 Con_DPrintf("Loading shaders from file %s...\n", filename);
1030 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1032 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1033 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1034 return shaderstring;
1036 if (!strcmp(filename, "hlsl/default.hlsl"))
1039 return R_ShaderStrCat(builtinhlslshaderstrings);
1040 if (!hlslshaderstring)
1042 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1043 if (hlslshaderstring)
1044 Con_DPrintf("Loading shaders from file %s...\n", filename);
1046 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1048 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1049 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1050 return shaderstring;
1052 // we don't have builtin strings for any other files
1055 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1058 if (printfromdisknotice)
1059 Con_DPrintf("from disk %s... ", filename);
1060 return shaderstring;
1062 return shaderstring;
1065 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1070 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1072 char permutationname[256];
1073 int vertstrings_count = 0;
1074 int geomstrings_count = 0;
1075 int fragstrings_count = 0;
1076 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1077 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1078 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1085 permutationname[0] = 0;
1086 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1088 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1090 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1091 if(vid.support.glshaderversion >= 140)
1093 vertstrings_list[vertstrings_count++] = "#version 140\n";
1094 geomstrings_list[geomstrings_count++] = "#version 140\n";
1095 fragstrings_list[fragstrings_count++] = "#version 140\n";
1096 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1097 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1098 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1100 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1101 else if(vid.support.glshaderversion >= 130)
1103 vertstrings_list[vertstrings_count++] = "#version 130\n";
1104 geomstrings_list[geomstrings_count++] = "#version 130\n";
1105 fragstrings_list[fragstrings_count++] = "#version 130\n";
1106 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1107 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1108 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1111 // the first pretext is which type of shader to compile as
1112 // (later these will all be bound together as a program object)
1113 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1114 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1115 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1117 // the second pretext is the mode (for example a light source)
1118 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1119 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1120 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1121 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1123 // now add all the permutation pretexts
1124 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1126 if (permutation & (1<<i))
1128 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1129 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1130 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1131 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1135 // keep line numbers correct
1136 vertstrings_list[vertstrings_count++] = "\n";
1137 geomstrings_list[geomstrings_count++] = "\n";
1138 fragstrings_list[fragstrings_count++] = "\n";
1143 R_CompileShader_AddStaticParms(mode, permutation);
1144 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1145 vertstrings_count += shaderstaticparms_count;
1146 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1147 geomstrings_count += shaderstaticparms_count;
1148 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149 fragstrings_count += shaderstaticparms_count;
1151 // now append the shader text itself
1152 vertstrings_list[vertstrings_count++] = sourcestring;
1153 geomstrings_list[geomstrings_count++] = sourcestring;
1154 fragstrings_list[fragstrings_count++] = sourcestring;
1156 // compile the shader program
1157 if (vertstrings_count + geomstrings_count + fragstrings_count)
1158 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1162 qglUseProgram(p->program);CHECKGLERROR
1163 // look up all the uniform variable names we care about, so we don't
1164 // have to look them up every time we set them
1169 GLint activeuniformindex = 0;
1170 GLint numactiveuniforms = 0;
1171 char uniformname[128];
1172 GLsizei uniformnamelength = 0;
1173 GLint uniformsize = 0;
1174 GLenum uniformtype = 0;
1175 memset(uniformname, 0, sizeof(uniformname));
1176 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1177 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1178 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1180 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1181 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1186 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1187 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1188 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1189 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1190 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1191 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1192 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1193 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1194 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1195 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1196 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1197 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1198 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1199 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1200 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1201 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1202 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1203 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1204 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1205 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1206 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1207 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1208 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1209 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1210 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1211 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1212 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1213 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1214 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1215 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1216 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1217 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1218 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1219 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1220 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1221 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1222 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1223 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1224 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1225 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1226 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1227 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1228 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1229 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1230 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1231 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1232 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1233 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1234 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1235 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1236 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1237 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1238 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1239 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1240 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1241 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1242 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1243 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1244 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1245 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1246 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1247 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1248 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1249 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1250 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1251 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1252 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1253 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1254 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1255 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1256 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1257 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1258 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1259 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1260 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1261 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1262 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1263 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1264 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1265 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1266 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1267 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1268 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1269 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1270 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1271 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1272 // initialize the samplers to refer to the texture units we use
1273 p->tex_Texture_First = -1;
1274 p->tex_Texture_Second = -1;
1275 p->tex_Texture_GammaRamps = -1;
1276 p->tex_Texture_Normal = -1;
1277 p->tex_Texture_Color = -1;
1278 p->tex_Texture_Gloss = -1;
1279 p->tex_Texture_Glow = -1;
1280 p->tex_Texture_SecondaryNormal = -1;
1281 p->tex_Texture_SecondaryColor = -1;
1282 p->tex_Texture_SecondaryGloss = -1;
1283 p->tex_Texture_SecondaryGlow = -1;
1284 p->tex_Texture_Pants = -1;
1285 p->tex_Texture_Shirt = -1;
1286 p->tex_Texture_FogHeightTexture = -1;
1287 p->tex_Texture_FogMask = -1;
1288 p->tex_Texture_Lightmap = -1;
1289 p->tex_Texture_Deluxemap = -1;
1290 p->tex_Texture_Attenuation = -1;
1291 p->tex_Texture_Cube = -1;
1292 p->tex_Texture_Refraction = -1;
1293 p->tex_Texture_Reflection = -1;
1294 p->tex_Texture_ShadowMap2D = -1;
1295 p->tex_Texture_CubeProjection = -1;
1296 p->tex_Texture_ScreenNormalMap = -1;
1297 p->tex_Texture_ScreenDiffuse = -1;
1298 p->tex_Texture_ScreenSpecular = -1;
1299 p->tex_Texture_ReflectMask = -1;
1300 p->tex_Texture_ReflectCube = -1;
1301 p->tex_Texture_BounceGrid = -1;
1302 // bind the texture samplers in use
1304 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1305 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1306 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1307 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1308 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1309 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1310 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1311 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1312 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1313 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1314 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1315 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1316 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1317 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1318 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1319 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1320 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1321 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1322 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1323 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1324 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1325 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1326 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1327 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1328 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1329 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1330 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1331 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1332 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1333 // get the uniform block indices so we can bind them
1334 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1335 if (vid.support.arb_uniform_buffer_object)
1336 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1339 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1340 // clear the uniform block bindings
1341 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1342 // bind the uniform blocks in use
1344 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1345 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1347 // we're done compiling and setting up the shader, at least until it is used
1349 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1352 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1356 Mem_Free(sourcestring);
1359 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1361 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1362 if (r_glsl_permutation != perm)
1364 r_glsl_permutation = perm;
1365 if (!r_glsl_permutation->program)
1367 if (!r_glsl_permutation->compiled)
1369 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1370 R_GLSL_CompilePermutation(perm, mode, permutation);
1372 if (!r_glsl_permutation->program)
1374 // remove features until we find a valid permutation
1376 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1378 // reduce i more quickly whenever it would not remove any bits
1379 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1380 if (!(permutation & j))
1383 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1384 if (!r_glsl_permutation->compiled)
1385 R_GLSL_CompilePermutation(perm, mode, permutation);
1386 if (r_glsl_permutation->program)
1389 if (i >= SHADERPERMUTATION_COUNT)
1391 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1392 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1393 qglUseProgram(0);CHECKGLERROR
1394 return; // no bit left to clear, entire mode is broken
1399 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1401 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1402 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1403 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1411 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1412 extern D3DCAPS9 vid_d3d9caps;
1415 struct r_hlsl_permutation_s;
1416 typedef struct r_hlsl_permutation_s
1418 /// hash lookup data
1419 struct r_hlsl_permutation_s *hashnext;
1421 unsigned int permutation;
1423 /// indicates if we have tried compiling this permutation already
1425 /// NULL if compilation failed
1426 IDirect3DVertexShader9 *vertexshader;
1427 IDirect3DPixelShader9 *pixelshader;
1429 r_hlsl_permutation_t;
1431 typedef enum D3DVSREGISTER_e
1433 D3DVSREGISTER_TexMatrix = 0, // float4x4
1434 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1435 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1436 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1437 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1438 D3DVSREGISTER_ModelToLight = 20, // float4x4
1439 D3DVSREGISTER_EyePosition = 24,
1440 D3DVSREGISTER_FogPlane = 25,
1441 D3DVSREGISTER_LightDir = 26,
1442 D3DVSREGISTER_LightPosition = 27,
1446 typedef enum D3DPSREGISTER_e
1448 D3DPSREGISTER_Alpha = 0,
1449 D3DPSREGISTER_BloomBlur_Parameters = 1,
1450 D3DPSREGISTER_ClientTime = 2,
1451 D3DPSREGISTER_Color_Ambient = 3,
1452 D3DPSREGISTER_Color_Diffuse = 4,
1453 D3DPSREGISTER_Color_Specular = 5,
1454 D3DPSREGISTER_Color_Glow = 6,
1455 D3DPSREGISTER_Color_Pants = 7,
1456 D3DPSREGISTER_Color_Shirt = 8,
1457 D3DPSREGISTER_DeferredColor_Ambient = 9,
1458 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1459 D3DPSREGISTER_DeferredColor_Specular = 11,
1460 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1461 D3DPSREGISTER_DeferredMod_Specular = 13,
1462 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1463 D3DPSREGISTER_EyePosition = 15, // unused
1464 D3DPSREGISTER_FogColor = 16,
1465 D3DPSREGISTER_FogHeightFade = 17,
1466 D3DPSREGISTER_FogPlane = 18,
1467 D3DPSREGISTER_FogPlaneViewDist = 19,
1468 D3DPSREGISTER_FogRangeRecip = 20,
1469 D3DPSREGISTER_LightColor = 21,
1470 D3DPSREGISTER_LightDir = 22, // unused
1471 D3DPSREGISTER_LightPosition = 23,
1472 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1473 D3DPSREGISTER_PixelSize = 25,
1474 D3DPSREGISTER_ReflectColor = 26,
1475 D3DPSREGISTER_ReflectFactor = 27,
1476 D3DPSREGISTER_ReflectOffset = 28,
1477 D3DPSREGISTER_RefractColor = 29,
1478 D3DPSREGISTER_Saturation = 30,
1479 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1480 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1481 D3DPSREGISTER_ScreenToDepth = 33,
1482 D3DPSREGISTER_ShadowMap_Parameters = 34,
1483 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1484 D3DPSREGISTER_SpecularPower = 36,
1485 D3DPSREGISTER_UserVec1 = 37,
1486 D3DPSREGISTER_UserVec2 = 38,
1487 D3DPSREGISTER_UserVec3 = 39,
1488 D3DPSREGISTER_UserVec4 = 40,
1489 D3DPSREGISTER_ViewTintColor = 41,
1490 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1491 D3DPSREGISTER_BloomColorSubtract = 43,
1492 D3DPSREGISTER_ViewToLight = 44, // float4x4
1493 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1494 D3DPSREGISTER_NormalmapScrollBlend = 52,
1495 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1496 D3DPSREGISTER_OffsetMapping_Bias = 54,
1501 /// information about each possible shader permutation
1502 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1503 /// currently selected permutation
1504 r_hlsl_permutation_t *r_hlsl_permutation;
1505 /// storage for permutations linked in the hash table
1506 memexpandablearray_t r_hlsl_permutationarray;
1508 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1510 //unsigned int hashdepth = 0;
1511 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1512 r_hlsl_permutation_t *p;
1513 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1515 if (p->mode == mode && p->permutation == permutation)
1517 //if (hashdepth > 10)
1518 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1523 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1525 p->permutation = permutation;
1526 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1527 r_hlsl_permutationhash[mode][hashindex] = p;
1528 //if (hashdepth > 10)
1529 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1534 //#include <d3dx9shader.h>
1535 //#include <d3dx9mesh.h>
1537 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1539 DWORD *vsbin = NULL;
1540 DWORD *psbin = NULL;
1541 fs_offset_t vsbinsize;
1542 fs_offset_t psbinsize;
1543 // IDirect3DVertexShader9 *vs = NULL;
1544 // IDirect3DPixelShader9 *ps = NULL;
1545 ID3DXBuffer *vslog = NULL;
1546 ID3DXBuffer *vsbuffer = NULL;
1547 ID3DXConstantTable *vsconstanttable = NULL;
1548 ID3DXBuffer *pslog = NULL;
1549 ID3DXBuffer *psbuffer = NULL;
1550 ID3DXConstantTable *psconstanttable = NULL;
1553 char temp[MAX_INPUTLINE];
1554 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1556 qboolean debugshader = gl_paranoid.integer != 0;
1557 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1558 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1561 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1562 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1564 if ((!vsbin && vertstring) || (!psbin && fragstring))
1566 const char* dllnames_d3dx9 [] =
1590 dllhandle_t d3dx9_dll = NULL;
1591 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1592 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1593 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1594 dllfunction_t d3dx9_dllfuncs[] =
1596 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1597 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1598 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1601 // 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...
1602 #ifndef ID3DXBuffer_GetBufferPointer
1603 #if !defined(__cplusplus) || defined(CINTERFACE)
1604 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1605 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1606 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1608 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1609 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1610 #define ID3DXBuffer_Release(p) (p)->Release()
1613 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1615 DWORD shaderflags = 0;
1617 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1618 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1619 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1620 if (vertstring && vertstring[0])
1624 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1625 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1628 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1631 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1632 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1633 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1634 ID3DXBuffer_Release(vsbuffer);
1638 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1639 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1640 ID3DXBuffer_Release(vslog);
1643 if (fragstring && fragstring[0])
1647 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1648 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1651 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1654 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1655 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1656 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1657 ID3DXBuffer_Release(psbuffer);
1661 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1662 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1663 ID3DXBuffer_Release(pslog);
1666 Sys_UnloadLibrary(&d3dx9_dll);
1669 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1673 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1674 if (FAILED(vsresult))
1675 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1676 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1677 if (FAILED(psresult))
1678 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1680 // free the shader data
1681 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1682 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1685 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1688 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1689 int vertstring_length = 0;
1690 int geomstring_length = 0;
1691 int fragstring_length = 0;
1694 char *vertstring, *geomstring, *fragstring;
1695 char permutationname[256];
1696 char cachename[256];
1697 int vertstrings_count = 0;
1698 int geomstrings_count = 0;
1699 int fragstrings_count = 0;
1700 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1701 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1702 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1707 p->vertexshader = NULL;
1708 p->pixelshader = NULL;
1710 permutationname[0] = 0;
1712 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1714 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1715 strlcat(cachename, "hlsl/", sizeof(cachename));
1717 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1718 vertstrings_count = 0;
1719 geomstrings_count = 0;
1720 fragstrings_count = 0;
1721 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1722 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1723 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1725 // the first pretext is which type of shader to compile as
1726 // (later these will all be bound together as a program object)
1727 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1728 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1729 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1731 // the second pretext is the mode (for example a light source)
1732 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1733 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1734 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1735 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1736 strlcat(cachename, modeinfo->name, sizeof(cachename));
1738 // now add all the permutation pretexts
1739 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1741 if (permutation & (1<<i))
1743 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1744 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1745 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1746 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1747 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1751 // keep line numbers correct
1752 vertstrings_list[vertstrings_count++] = "\n";
1753 geomstrings_list[geomstrings_count++] = "\n";
1754 fragstrings_list[fragstrings_count++] = "\n";
1759 R_CompileShader_AddStaticParms(mode, permutation);
1760 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1761 vertstrings_count += shaderstaticparms_count;
1762 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1763 geomstrings_count += shaderstaticparms_count;
1764 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1765 fragstrings_count += shaderstaticparms_count;
1767 // replace spaces in the cachename with _ characters
1768 for (i = 0;cachename[i];i++)
1769 if (cachename[i] == ' ')
1772 // now append the shader text itself
1773 vertstrings_list[vertstrings_count++] = sourcestring;
1774 geomstrings_list[geomstrings_count++] = sourcestring;
1775 fragstrings_list[fragstrings_count++] = sourcestring;
1777 vertstring_length = 0;
1778 for (i = 0;i < vertstrings_count;i++)
1779 vertstring_length += strlen(vertstrings_list[i]);
1780 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1781 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1782 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1784 geomstring_length = 0;
1785 for (i = 0;i < geomstrings_count;i++)
1786 geomstring_length += strlen(geomstrings_list[i]);
1787 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1788 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1789 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1791 fragstring_length = 0;
1792 for (i = 0;i < fragstrings_count;i++)
1793 fragstring_length += strlen(fragstrings_list[i]);
1794 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1795 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1796 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1798 // try to load the cached shader, or generate one
1799 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1801 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1802 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1804 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1808 Mem_Free(vertstring);
1810 Mem_Free(geomstring);
1812 Mem_Free(fragstring);
1814 Mem_Free(sourcestring);
1817 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1818 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1819 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);}
1820 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);}
1821 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);}
1822 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);}
1824 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1825 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1826 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);}
1827 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);}
1828 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);}
1829 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);}
1831 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1833 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1834 if (r_hlsl_permutation != perm)
1836 r_hlsl_permutation = perm;
1837 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1839 if (!r_hlsl_permutation->compiled)
1840 R_HLSL_CompilePermutation(perm, mode, permutation);
1841 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1843 // remove features until we find a valid permutation
1845 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1847 // reduce i more quickly whenever it would not remove any bits
1848 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1849 if (!(permutation & j))
1852 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1853 if (!r_hlsl_permutation->compiled)
1854 R_HLSL_CompilePermutation(perm, mode, permutation);
1855 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1858 if (i >= SHADERPERMUTATION_COUNT)
1860 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1861 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1862 return; // no bit left to clear, entire mode is broken
1866 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1867 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1869 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1870 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1871 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1875 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1877 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1878 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1879 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1880 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1883 void R_GLSL_Restart_f(void)
1885 unsigned int i, limit;
1886 if (glslshaderstring)
1887 Mem_Free(glslshaderstring);
1888 glslshaderstring = NULL;
1889 if (hlslshaderstring)
1890 Mem_Free(hlslshaderstring);
1891 hlslshaderstring = NULL;
1892 switch(vid.renderpath)
1894 case RENDERPATH_D3D9:
1897 r_hlsl_permutation_t *p;
1898 r_hlsl_permutation = NULL;
1899 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1900 for (i = 0;i < limit;i++)
1902 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1904 if (p->vertexshader)
1905 IDirect3DVertexShader9_Release(p->vertexshader);
1907 IDirect3DPixelShader9_Release(p->pixelshader);
1908 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1911 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1915 case RENDERPATH_D3D10:
1916 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918 case RENDERPATH_D3D11:
1919 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1921 case RENDERPATH_GL20:
1922 case RENDERPATH_GLES2:
1924 r_glsl_permutation_t *p;
1925 r_glsl_permutation = NULL;
1926 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1927 for (i = 0;i < limit;i++)
1929 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1931 GL_Backend_FreeProgram(p->program);
1932 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1935 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1938 case RENDERPATH_GL11:
1939 case RENDERPATH_GL13:
1940 case RENDERPATH_GLES1:
1942 case RENDERPATH_SOFT:
1947 static void R_GLSL_DumpShader_f(void)
1949 int i, language, mode, dupe;
1951 shadermodeinfo_t *modeinfo;
1954 for (language = 0;language < 2;language++)
1956 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1957 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1959 // don't dump the same file multiple times (most or all shaders come from the same file)
1960 for (dupe = mode - 1;dupe >= 0;dupe--)
1961 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1965 text = R_GetShaderText(modeinfo[mode].filename, false, true);
1968 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1971 FS_Print(file, "/* The engine may define the following macros:\n");
1972 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1973 for (i = 0;i < SHADERMODE_COUNT;i++)
1974 FS_Print(file, modeinfo[i].pretext);
1975 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1976 FS_Print(file, shaderpermutationinfo[i].pretext);
1977 FS_Print(file, "*/\n");
1978 FS_Print(file, text);
1980 Con_Printf("%s written\n", modeinfo[mode].filename);
1983 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1989 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1991 unsigned int permutation = 0;
1992 if (r_trippy.integer && !notrippy)
1993 permutation |= SHADERPERMUTATION_TRIPPY;
1994 permutation |= SHADERPERMUTATION_VIEWTINT;
1996 permutation |= SHADERPERMUTATION_DIFFUSE;
1998 permutation |= SHADERPERMUTATION_SPECULAR;
1999 if (texturemode == GL_MODULATE)
2000 permutation |= SHADERPERMUTATION_COLORMAPPING;
2001 else if (texturemode == GL_ADD)
2002 permutation |= SHADERPERMUTATION_GLOW;
2003 else if (texturemode == GL_DECAL)
2004 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2005 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2006 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2007 if (suppresstexalpha)
2008 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2010 texturemode = GL_MODULATE;
2011 if (vid.allowalphatocoverage)
2012 GL_AlphaToCoverage(false);
2013 switch (vid.renderpath)
2015 case RENDERPATH_D3D9:
2017 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2018 R_Mesh_TexBind(GL20TU_FIRST , first );
2019 R_Mesh_TexBind(GL20TU_SECOND, second);
2020 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2021 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2024 case RENDERPATH_D3D10:
2025 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2027 case RENDERPATH_D3D11:
2028 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2030 case RENDERPATH_GL20:
2031 case RENDERPATH_GLES2:
2032 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2033 if (r_glsl_permutation->tex_Texture_First >= 0)
2034 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2035 if (r_glsl_permutation->tex_Texture_Second >= 0)
2036 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2037 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2038 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2040 case RENDERPATH_GL13:
2041 case RENDERPATH_GLES1:
2042 R_Mesh_TexBind(0, first );
2043 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2044 R_Mesh_TexMatrix(0, NULL);
2045 R_Mesh_TexBind(1, second);
2048 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2049 R_Mesh_TexMatrix(1, NULL);
2052 case RENDERPATH_GL11:
2053 R_Mesh_TexBind(0, first );
2054 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2055 R_Mesh_TexMatrix(0, NULL);
2057 case RENDERPATH_SOFT:
2058 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2059 R_Mesh_TexBind(GL20TU_FIRST , first );
2060 R_Mesh_TexBind(GL20TU_SECOND, second);
2065 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2067 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2070 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2072 unsigned int permutation = 0;
2073 if (r_trippy.integer && !notrippy)
2074 permutation |= SHADERPERMUTATION_TRIPPY;
2076 permutation |= SHADERPERMUTATION_DEPTHRGB;
2078 permutation |= SHADERPERMUTATION_SKELETAL;
2080 if (vid.allowalphatocoverage)
2081 GL_AlphaToCoverage(false);
2082 switch (vid.renderpath)
2084 case RENDERPATH_D3D9:
2086 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2089 case RENDERPATH_D3D10:
2090 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2092 case RENDERPATH_D3D11:
2093 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2095 case RENDERPATH_GL20:
2096 case RENDERPATH_GLES2:
2097 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2098 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2099 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);
2102 case RENDERPATH_GL13:
2103 case RENDERPATH_GLES1:
2104 R_Mesh_TexBind(0, 0);
2105 R_Mesh_TexBind(1, 0);
2107 case RENDERPATH_GL11:
2108 R_Mesh_TexBind(0, 0);
2110 case RENDERPATH_SOFT:
2111 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2116 extern qboolean r_shadow_usingdeferredprepass;
2117 extern rtexture_t *r_shadow_attenuationgradienttexture;
2118 extern rtexture_t *r_shadow_attenuation2dtexture;
2119 extern rtexture_t *r_shadow_attenuation3dtexture;
2120 extern qboolean r_shadow_usingshadowmap2d;
2121 extern qboolean r_shadow_usingshadowmaportho;
2122 extern float r_shadow_shadowmap_texturescale[2];
2123 extern float r_shadow_shadowmap_parameters[4];
2124 extern qboolean r_shadow_shadowmapvsdct;
2125 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2126 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2127 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2128 extern matrix4x4_t r_shadow_shadowmapmatrix;
2129 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2130 extern int r_shadow_prepass_width;
2131 extern int r_shadow_prepass_height;
2132 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2133 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2134 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2135 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2137 #define BLENDFUNC_ALLOWS_COLORMOD 1
2138 #define BLENDFUNC_ALLOWS_FOG 2
2139 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2140 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2141 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2142 static int R_BlendFuncFlags(int src, int dst)
2146 // a blendfunc allows colormod if:
2147 // a) it can never keep the destination pixel invariant, or
2148 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2149 // this is to prevent unintended side effects from colormod
2151 // a blendfunc allows fog if:
2152 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2153 // this is to prevent unintended side effects from fog
2155 // these checks are the output of fogeval.pl
2157 r |= BLENDFUNC_ALLOWS_COLORMOD;
2158 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2159 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2160 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2161 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2162 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2163 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2164 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2165 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2166 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2167 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2168 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2169 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2170 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2171 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2172 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2173 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2174 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2175 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2177 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2178 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2183 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)
2185 // select a permutation of the lighting shader appropriate to this
2186 // combination of texture, entity, light source, and fogging, only use the
2187 // minimum features necessary to avoid wasting rendering time in the
2188 // fragment shader on features that are not being used
2189 unsigned int permutation = 0;
2190 unsigned int mode = 0;
2192 static float dummy_colormod[3] = {1, 1, 1};
2193 float *colormod = rsurface.colormod;
2195 matrix4x4_t tempmatrix;
2196 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2197 if (r_trippy.integer && !notrippy)
2198 permutation |= SHADERPERMUTATION_TRIPPY;
2199 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2200 permutation |= SHADERPERMUTATION_ALPHAKILL;
2201 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2202 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2203 if (rsurfacepass == RSURFPASS_BACKGROUND)
2205 // distorted background
2206 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2208 mode = SHADERMODE_WATER;
2209 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2210 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2211 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2213 // this is the right thing to do for wateralpha
2214 GL_BlendFunc(GL_ONE, GL_ZERO);
2215 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2219 // this is the right thing to do for entity alpha
2220 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2221 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2224 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2226 mode = SHADERMODE_REFRACTION;
2227 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2228 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2229 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2230 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2234 mode = SHADERMODE_GENERIC;
2235 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2236 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2237 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2239 if (vid.allowalphatocoverage)
2240 GL_AlphaToCoverage(false);
2242 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2244 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2246 switch(rsurface.texture->offsetmapping)
2248 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2249 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2250 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2251 case OFFSETMAPPING_OFF: break;
2254 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2255 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2256 // normalmap (deferred prepass), may use alpha test on diffuse
2257 mode = SHADERMODE_DEFERREDGEOMETRY;
2258 GL_BlendFunc(GL_ONE, GL_ZERO);
2259 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2260 if (vid.allowalphatocoverage)
2261 GL_AlphaToCoverage(false);
2263 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2265 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2267 switch(rsurface.texture->offsetmapping)
2269 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2270 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2271 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2272 case OFFSETMAPPING_OFF: break;
2275 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2276 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2277 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2278 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2280 mode = SHADERMODE_LIGHTSOURCE;
2281 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2282 permutation |= SHADERPERMUTATION_CUBEFILTER;
2283 if (diffusescale > 0)
2284 permutation |= SHADERPERMUTATION_DIFFUSE;
2285 if (specularscale > 0)
2286 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2287 if (r_refdef.fogenabled)
2288 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2289 if (rsurface.texture->colormapping)
2290 permutation |= SHADERPERMUTATION_COLORMAPPING;
2291 if (r_shadow_usingshadowmap2d)
2293 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2294 if(r_shadow_shadowmapvsdct)
2295 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2297 if (r_shadow_shadowmap2ddepthbuffer)
2298 permutation |= SHADERPERMUTATION_DEPTHRGB;
2300 if (rsurface.texture->reflectmasktexture)
2301 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2302 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2303 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2304 if (vid.allowalphatocoverage)
2305 GL_AlphaToCoverage(false);
2307 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2309 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2311 switch(rsurface.texture->offsetmapping)
2313 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2314 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2316 case OFFSETMAPPING_OFF: break;
2319 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2320 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2321 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2322 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2323 // unshaded geometry (fullbright or ambient model lighting)
2324 mode = SHADERMODE_FLATCOLOR;
2325 ambientscale = diffusescale = specularscale = 0;
2326 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2327 permutation |= SHADERPERMUTATION_GLOW;
2328 if (r_refdef.fogenabled)
2329 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2330 if (rsurface.texture->colormapping)
2331 permutation |= SHADERPERMUTATION_COLORMAPPING;
2332 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2334 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2335 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2337 if (r_shadow_shadowmap2ddepthbuffer)
2338 permutation |= SHADERPERMUTATION_DEPTHRGB;
2340 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2341 permutation |= SHADERPERMUTATION_REFLECTION;
2342 if (rsurface.texture->reflectmasktexture)
2343 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2344 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2345 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2346 // when using alphatocoverage, we don't need alphakill
2347 if (vid.allowalphatocoverage)
2349 if (r_transparent_alphatocoverage.integer)
2351 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2352 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2355 GL_AlphaToCoverage(false);
2358 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2360 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2362 switch(rsurface.texture->offsetmapping)
2364 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2365 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2366 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2367 case OFFSETMAPPING_OFF: break;
2370 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2371 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2372 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2373 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2374 // directional model lighting
2375 mode = SHADERMODE_LIGHTDIRECTION;
2376 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2377 permutation |= SHADERPERMUTATION_GLOW;
2378 permutation |= SHADERPERMUTATION_DIFFUSE;
2379 if (specularscale > 0)
2380 permutation |= SHADERPERMUTATION_SPECULAR;
2381 if (r_refdef.fogenabled)
2382 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2383 if (rsurface.texture->colormapping)
2384 permutation |= SHADERPERMUTATION_COLORMAPPING;
2385 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2387 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2388 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2390 if (r_shadow_shadowmap2ddepthbuffer)
2391 permutation |= SHADERPERMUTATION_DEPTHRGB;
2393 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2394 permutation |= SHADERPERMUTATION_REFLECTION;
2395 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2396 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2397 if (rsurface.texture->reflectmasktexture)
2398 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2399 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2401 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2402 if (r_shadow_bouncegriddirectional)
2403 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2405 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2406 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2407 // when using alphatocoverage, we don't need alphakill
2408 if (vid.allowalphatocoverage)
2410 if (r_transparent_alphatocoverage.integer)
2412 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2413 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2416 GL_AlphaToCoverage(false);
2419 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2421 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2423 switch(rsurface.texture->offsetmapping)
2425 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2426 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2427 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2428 case OFFSETMAPPING_OFF: break;
2431 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2432 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2434 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2435 // ambient model lighting
2436 mode = SHADERMODE_LIGHTDIRECTION;
2437 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2438 permutation |= SHADERPERMUTATION_GLOW;
2439 if (r_refdef.fogenabled)
2440 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2441 if (rsurface.texture->colormapping)
2442 permutation |= SHADERPERMUTATION_COLORMAPPING;
2443 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2445 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2446 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2448 if (r_shadow_shadowmap2ddepthbuffer)
2449 permutation |= SHADERPERMUTATION_DEPTHRGB;
2451 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2452 permutation |= SHADERPERMUTATION_REFLECTION;
2453 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2454 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2455 if (rsurface.texture->reflectmasktexture)
2456 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2457 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2459 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2460 if (r_shadow_bouncegriddirectional)
2461 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2463 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2464 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2465 // when using alphatocoverage, we don't need alphakill
2466 if (vid.allowalphatocoverage)
2468 if (r_transparent_alphatocoverage.integer)
2470 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2471 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2474 GL_AlphaToCoverage(false);
2479 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2481 switch(rsurface.texture->offsetmapping)
2483 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2484 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2485 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2486 case OFFSETMAPPING_OFF: break;
2489 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2490 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2491 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2492 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2494 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2495 permutation |= SHADERPERMUTATION_GLOW;
2496 if (r_refdef.fogenabled)
2497 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2498 if (rsurface.texture->colormapping)
2499 permutation |= SHADERPERMUTATION_COLORMAPPING;
2500 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2502 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2503 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2505 if (r_shadow_shadowmap2ddepthbuffer)
2506 permutation |= SHADERPERMUTATION_DEPTHRGB;
2508 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2509 permutation |= SHADERPERMUTATION_REFLECTION;
2510 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2511 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2512 if (rsurface.texture->reflectmasktexture)
2513 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2514 if (FAKELIGHT_ENABLED)
2516 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2517 mode = SHADERMODE_FAKELIGHT;
2518 permutation |= SHADERPERMUTATION_DIFFUSE;
2519 if (specularscale > 0)
2520 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2522 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2524 // deluxemapping (light direction texture)
2525 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2526 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2528 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2529 permutation |= SHADERPERMUTATION_DIFFUSE;
2530 if (specularscale > 0)
2531 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2533 else if (r_glsl_deluxemapping.integer >= 2)
2535 // fake deluxemapping (uniform light direction in tangentspace)
2536 if (rsurface.uselightmaptexture)
2537 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2539 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2540 permutation |= SHADERPERMUTATION_DIFFUSE;
2541 if (specularscale > 0)
2542 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2544 else if (rsurface.uselightmaptexture)
2546 // ordinary lightmapping (q1bsp, q3bsp)
2547 mode = SHADERMODE_LIGHTMAP;
2551 // ordinary vertex coloring (q3bsp)
2552 mode = SHADERMODE_VERTEXCOLOR;
2554 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2556 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2557 if (r_shadow_bouncegriddirectional)
2558 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2560 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2561 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2562 // when using alphatocoverage, we don't need alphakill
2563 if (vid.allowalphatocoverage)
2565 if (r_transparent_alphatocoverage.integer)
2567 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2568 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2571 GL_AlphaToCoverage(false);
2574 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2575 colormod = dummy_colormod;
2576 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2577 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2578 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2579 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2580 switch(vid.renderpath)
2582 case RENDERPATH_D3D9:
2584 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);
2585 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2586 R_SetupShader_SetPermutationHLSL(mode, permutation);
2587 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2588 if (mode == SHADERMODE_LIGHTSOURCE)
2590 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2591 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2595 if (mode == SHADERMODE_LIGHTDIRECTION)
2597 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2600 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2601 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2602 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2603 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2604 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2606 if (mode == SHADERMODE_LIGHTSOURCE)
2608 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2609 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2610 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2611 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2612 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2614 // additive passes are only darkened by fog, not tinted
2615 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2616 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2620 if (mode == SHADERMODE_FLATCOLOR)
2622 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2624 else if (mode == SHADERMODE_LIGHTDIRECTION)
2626 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]);
2627 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2628 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);
2629 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2630 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2631 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2632 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2636 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2637 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2638 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);
2639 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2640 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2642 // additive passes are only darkened by fog, not tinted
2643 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2644 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2646 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2647 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);
2648 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2649 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2650 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2651 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2652 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2653 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2654 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2655 if (mode == SHADERMODE_WATER)
2656 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2658 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2659 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2660 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2661 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));
2662 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2663 if (rsurface.texture->pantstexture)
2664 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2666 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2667 if (rsurface.texture->shirttexture)
2668 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2670 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2671 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2672 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2673 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2674 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2675 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2676 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2677 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2678 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2679 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2681 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2682 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2683 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2684 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2686 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2687 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2688 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2689 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2690 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2691 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2692 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2693 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2694 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2695 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2696 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2697 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2698 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2699 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2700 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2701 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2702 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2703 if (rsurfacepass == RSURFPASS_BACKGROUND)
2705 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2706 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2707 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2711 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2713 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2714 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2715 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2716 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2718 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2719 if (rsurface.rtlight)
2721 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2722 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2727 case RENDERPATH_D3D10:
2728 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2730 case RENDERPATH_D3D11:
2731 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2733 case RENDERPATH_GL20:
2734 case RENDERPATH_GLES2:
2735 if (!vid.useinterleavedarrays)
2737 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);
2738 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2739 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2740 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2741 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2742 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2743 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2744 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2745 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2746 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2747 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2751 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);
2752 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2754 // this has to be after RSurf_PrepareVerticesForBatch
2755 if (rsurface.batchskeletaltransform3x4buffer)
2756 permutation |= SHADERPERMUTATION_SKELETAL;
2757 R_SetupShader_SetPermutationGLSL(mode, permutation);
2758 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2759 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);
2761 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2762 if (mode == SHADERMODE_LIGHTSOURCE)
2764 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2765 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2766 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2767 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2768 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2769 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);
2771 // additive passes are only darkened by fog, not tinted
2772 if (r_glsl_permutation->loc_FogColor >= 0)
2773 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2774 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);
2778 if (mode == SHADERMODE_FLATCOLOR)
2780 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2782 else if (mode == SHADERMODE_LIGHTDIRECTION)
2784 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]);
2785 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]);
2786 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);
2787 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2788 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2789 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]);
2790 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]);
2794 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]);
2795 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]);
2796 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);
2797 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2798 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2800 // additive passes are only darkened by fog, not tinted
2801 if (r_glsl_permutation->loc_FogColor >= 0)
2803 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2804 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2806 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2808 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);
2809 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]);
2810 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]);
2811 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]);
2812 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]);
2813 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2814 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2815 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);
2816 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]);
2818 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2819 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2820 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2821 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]);
2822 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]);
2824 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2825 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));
2826 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2827 if (r_glsl_permutation->loc_Color_Pants >= 0)
2829 if (rsurface.texture->pantstexture)
2830 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2832 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2834 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2836 if (rsurface.texture->shirttexture)
2837 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2839 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2841 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]);
2842 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2843 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2844 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2845 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2846 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2847 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2848 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2849 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2851 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);
2852 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2853 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]);
2854 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2855 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);}
2856 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2858 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2859 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2860 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2861 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2862 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2863 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2864 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2865 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2866 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2867 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2868 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2869 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2870 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2871 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2872 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);
2873 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2874 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2875 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2876 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2877 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2878 if (rsurfacepass == RSURFPASS_BACKGROUND)
2880 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);
2881 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);
2882 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);
2886 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);
2888 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2889 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2890 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2891 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2893 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2894 if (rsurface.rtlight)
2896 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2897 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2900 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2903 case RENDERPATH_GL11:
2904 case RENDERPATH_GL13:
2905 case RENDERPATH_GLES1:
2907 case RENDERPATH_SOFT:
2908 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);
2909 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2910 R_SetupShader_SetPermutationSoft(mode, permutation);
2911 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2912 if (mode == SHADERMODE_LIGHTSOURCE)
2914 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2915 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2916 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2917 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2918 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2919 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2921 // additive passes are only darkened by fog, not tinted
2922 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2923 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2927 if (mode == SHADERMODE_FLATCOLOR)
2929 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2931 else if (mode == SHADERMODE_LIGHTDIRECTION)
2933 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]);
2934 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2935 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);
2936 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2937 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2938 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]);
2939 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2943 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2944 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2945 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);
2946 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2947 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2949 // additive passes are only darkened by fog, not tinted
2950 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2951 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2953 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2954 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);
2955 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]);
2956 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]);
2957 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]);
2958 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]);
2959 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2960 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2961 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2962 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2964 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2965 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2966 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2967 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2968 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]);
2970 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2971 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));
2972 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2973 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2975 if (rsurface.texture->pantstexture)
2976 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2978 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2980 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2982 if (rsurface.texture->shirttexture)
2983 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2985 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2987 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2988 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2989 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2990 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2991 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2992 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2993 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2994 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2995 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2997 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2998 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2999 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3000 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3002 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3003 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3004 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3005 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3006 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3007 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3008 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3009 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3010 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3011 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3012 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3013 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3014 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3015 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3016 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3017 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3018 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3019 if (rsurfacepass == RSURFPASS_BACKGROUND)
3021 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3022 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3023 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3027 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3029 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3030 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3031 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3032 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3034 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3035 if (rsurface.rtlight)
3037 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3038 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3045 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3047 // select a permutation of the lighting shader appropriate to this
3048 // combination of texture, entity, light source, and fogging, only use the
3049 // minimum features necessary to avoid wasting rendering time in the
3050 // fragment shader on features that are not being used
3051 unsigned int permutation = 0;
3052 unsigned int mode = 0;
3053 const float *lightcolorbase = rtlight->currentcolor;
3054 float ambientscale = rtlight->ambientscale;
3055 float diffusescale = rtlight->diffusescale;
3056 float specularscale = rtlight->specularscale;
3057 // this is the location of the light in view space
3058 vec3_t viewlightorigin;
3059 // this transforms from view space (camera) to light space (cubemap)
3060 matrix4x4_t viewtolight;
3061 matrix4x4_t lighttoview;
3062 float viewtolight16f[16];
3064 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3065 if (rtlight->currentcubemap != r_texture_whitecube)
3066 permutation |= SHADERPERMUTATION_CUBEFILTER;
3067 if (diffusescale > 0)
3068 permutation |= SHADERPERMUTATION_DIFFUSE;
3069 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3070 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3071 if (r_shadow_usingshadowmap2d)
3073 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3074 if (r_shadow_shadowmapvsdct)
3075 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3077 if (r_shadow_shadowmap2ddepthbuffer)
3078 permutation |= SHADERPERMUTATION_DEPTHRGB;
3080 if (vid.allowalphatocoverage)
3081 GL_AlphaToCoverage(false);
3082 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3083 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3084 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3085 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3086 switch(vid.renderpath)
3088 case RENDERPATH_D3D9:
3090 R_SetupShader_SetPermutationHLSL(mode, permutation);
3091 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3092 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3093 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3094 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3095 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3096 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3097 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3098 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);
3099 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3100 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3102 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3103 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3104 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3105 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3106 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3109 case RENDERPATH_D3D10:
3110 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3112 case RENDERPATH_D3D11:
3113 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3115 case RENDERPATH_GL20:
3116 case RENDERPATH_GLES2:
3117 R_SetupShader_SetPermutationGLSL(mode, permutation);
3118 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3119 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3120 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3121 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3122 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3123 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]);
3124 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]);
3125 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);
3126 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]);
3127 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3129 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3130 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3131 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3132 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3133 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3135 case RENDERPATH_GL11:
3136 case RENDERPATH_GL13:
3137 case RENDERPATH_GLES1:
3139 case RENDERPATH_SOFT:
3140 R_SetupShader_SetPermutationGLSL(mode, permutation);
3141 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3142 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3143 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3144 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3145 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3146 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3147 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]);
3148 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);
3149 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3150 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3152 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3153 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3154 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3155 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3156 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3161 #define SKINFRAME_HASH 1024
3165 int loadsequence; // incremented each level change
3166 memexpandablearray_t array;
3167 skinframe_t *hash[SKINFRAME_HASH];
3170 r_skinframe_t r_skinframe;
3172 void R_SkinFrame_PrepareForPurge(void)
3174 r_skinframe.loadsequence++;
3175 // wrap it without hitting zero
3176 if (r_skinframe.loadsequence >= 200)
3177 r_skinframe.loadsequence = 1;
3180 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3184 // mark the skinframe as used for the purging code
3185 skinframe->loadsequence = r_skinframe.loadsequence;
3188 void R_SkinFrame_Purge(void)
3192 for (i = 0;i < SKINFRAME_HASH;i++)
3194 for (s = r_skinframe.hash[i];s;s = s->next)
3196 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3198 if (s->merged == s->base)
3200 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3201 R_PurgeTexture(s->stain );s->stain = NULL;
3202 R_PurgeTexture(s->merged);s->merged = NULL;
3203 R_PurgeTexture(s->base );s->base = NULL;
3204 R_PurgeTexture(s->pants );s->pants = NULL;
3205 R_PurgeTexture(s->shirt );s->shirt = NULL;
3206 R_PurgeTexture(s->nmap );s->nmap = NULL;
3207 R_PurgeTexture(s->gloss );s->gloss = NULL;
3208 R_PurgeTexture(s->glow );s->glow = NULL;
3209 R_PurgeTexture(s->fog );s->fog = NULL;
3210 R_PurgeTexture(s->reflect);s->reflect = NULL;
3211 s->loadsequence = 0;
3217 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3219 char basename[MAX_QPATH];
3221 Image_StripImageExtension(name, basename, sizeof(basename));
3223 if( last == NULL ) {
3225 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3226 item = r_skinframe.hash[hashindex];
3231 // linearly search through the hash bucket
3232 for( ; item ; item = item->next ) {
3233 if( !strcmp( item->basename, basename ) ) {
3240 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3244 char basename[MAX_QPATH];
3246 Image_StripImageExtension(name, basename, sizeof(basename));
3248 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3249 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3250 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3254 rtexture_t *dyntexture;
3255 // check whether its a dynamic texture
3256 dyntexture = CL_GetDynTexture( basename );
3257 if (!add && !dyntexture)
3259 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3260 memset(item, 0, sizeof(*item));
3261 strlcpy(item->basename, basename, sizeof(item->basename));
3262 item->base = dyntexture; // either NULL or dyntexture handle
3263 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3264 item->comparewidth = comparewidth;
3265 item->compareheight = compareheight;
3266 item->comparecrc = comparecrc;
3267 item->next = r_skinframe.hash[hashindex];
3268 r_skinframe.hash[hashindex] = item;
3270 else if (textureflags & TEXF_FORCE_RELOAD)
3272 rtexture_t *dyntexture;
3273 // check whether its a dynamic texture
3274 dyntexture = CL_GetDynTexture( basename );
3275 if (!add && !dyntexture)
3277 if (item->merged == item->base)
3278 item->merged = NULL;
3279 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3280 R_PurgeTexture(item->stain );item->stain = NULL;
3281 R_PurgeTexture(item->merged);item->merged = NULL;
3282 R_PurgeTexture(item->base );item->base = NULL;
3283 R_PurgeTexture(item->pants );item->pants = NULL;
3284 R_PurgeTexture(item->shirt );item->shirt = NULL;
3285 R_PurgeTexture(item->nmap );item->nmap = NULL;
3286 R_PurgeTexture(item->gloss );item->gloss = NULL;
3287 R_PurgeTexture(item->glow );item->glow = NULL;
3288 R_PurgeTexture(item->fog );item->fog = NULL;
3289 R_PurgeTexture(item->reflect);item->reflect = NULL;
3290 item->loadsequence = 0;
3292 else if( item->base == NULL )
3294 rtexture_t *dyntexture;
3295 // check whether its a dynamic texture
3296 // 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]
3297 dyntexture = CL_GetDynTexture( basename );
3298 item->base = dyntexture; // either NULL or dyntexture handle
3301 R_SkinFrame_MarkUsed(item);
3305 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3307 unsigned long long avgcolor[5], wsum; \
3315 for(pix = 0; pix < cnt; ++pix) \
3318 for(comp = 0; comp < 3; ++comp) \
3320 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3323 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3325 for(comp = 0; comp < 3; ++comp) \
3326 avgcolor[comp] += getpixel * w; \
3329 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3330 avgcolor[4] += getpixel; \
3332 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3334 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3335 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3336 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3337 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3340 extern cvar_t gl_picmip;
3341 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3344 unsigned char *pixels;
3345 unsigned char *bumppixels;
3346 unsigned char *basepixels = NULL;
3347 int basepixels_width = 0;
3348 int basepixels_height = 0;
3349 skinframe_t *skinframe;
3350 rtexture_t *ddsbase = NULL;
3351 qboolean ddshasalpha = false;
3352 float ddsavgcolor[4];
3353 char basename[MAX_QPATH];
3354 int miplevel = R_PicmipForFlags(textureflags);
3355 int savemiplevel = miplevel;
3359 if (cls.state == ca_dedicated)
3362 // return an existing skinframe if already loaded
3363 // if loading of the first image fails, don't make a new skinframe as it
3364 // would cause all future lookups of this to be missing
3365 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3366 if (skinframe && skinframe->base)
3369 Image_StripImageExtension(name, basename, sizeof(basename));
3371 // check for DDS texture file first
3372 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3374 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3375 if (basepixels == NULL)
3379 // FIXME handle miplevel
3381 if (developer_loading.integer)
3382 Con_Printf("loading skin \"%s\"\n", name);
3384 // we've got some pixels to store, so really allocate this new texture now
3386 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3387 textureflags &= ~TEXF_FORCE_RELOAD;
3388 skinframe->stain = NULL;
3389 skinframe->merged = NULL;
3390 skinframe->base = NULL;
3391 skinframe->pants = NULL;
3392 skinframe->shirt = NULL;
3393 skinframe->nmap = NULL;
3394 skinframe->gloss = NULL;
3395 skinframe->glow = NULL;
3396 skinframe->fog = NULL;
3397 skinframe->reflect = NULL;
3398 skinframe->hasalpha = false;
3402 skinframe->base = ddsbase;
3403 skinframe->hasalpha = ddshasalpha;
3404 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3405 if (r_loadfog && skinframe->hasalpha)
3406 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);
3407 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3411 basepixels_width = image_width;
3412 basepixels_height = image_height;
3413 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);
3414 if (textureflags & TEXF_ALPHA)
3416 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3418 if (basepixels[j] < 255)
3420 skinframe->hasalpha = true;
3424 if (r_loadfog && skinframe->hasalpha)
3426 // has transparent pixels
3427 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3428 for (j = 0;j < image_width * image_height * 4;j += 4)
3433 pixels[j+3] = basepixels[j+3];
3435 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);
3439 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3441 //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]);
3442 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3443 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3444 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3445 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3451 mymiplevel = savemiplevel;
3452 if (r_loadnormalmap)
3453 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);
3454 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3456 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3457 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3458 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3459 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3462 // _norm is the name used by tenebrae and has been adopted as standard
3463 if (r_loadnormalmap && skinframe->nmap == NULL)
3465 mymiplevel = savemiplevel;
3466 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3468 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);
3472 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3474 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3475 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3476 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);
3478 Mem_Free(bumppixels);
3480 else if (r_shadow_bumpscale_basetexture.value > 0)
3482 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3483 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3484 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);
3488 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3489 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3493 // _luma is supported only for tenebrae compatibility
3494 // _glow is the preferred name
3495 mymiplevel = savemiplevel;
3496 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))))
3498 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);
3500 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3501 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3503 Mem_Free(pixels);pixels = NULL;
3506 mymiplevel = savemiplevel;
3507 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3509 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);
3511 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3512 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3518 mymiplevel = savemiplevel;
3519 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3521 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);
3523 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3524 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3530 mymiplevel = savemiplevel;
3531 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3533 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);
3535 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3536 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3542 mymiplevel = savemiplevel;
3543 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3545 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);
3547 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3548 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3555 Mem_Free(basepixels);
3560 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3561 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3564 unsigned char *temp1, *temp2;
3565 skinframe_t *skinframe;
3568 if (cls.state == ca_dedicated)
3571 // if already loaded just return it, otherwise make a new skinframe
3572 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3573 if (skinframe->base)
3575 textureflags &= ~TEXF_FORCE_RELOAD;
3577 skinframe->stain = NULL;
3578 skinframe->merged = NULL;
3579 skinframe->base = NULL;
3580 skinframe->pants = NULL;
3581 skinframe->shirt = NULL;
3582 skinframe->nmap = NULL;
3583 skinframe->gloss = NULL;
3584 skinframe->glow = NULL;
3585 skinframe->fog = NULL;
3586 skinframe->reflect = NULL;
3587 skinframe->hasalpha = false;
3589 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3593 if (developer_loading.integer)
3594 Con_Printf("loading 32bit skin \"%s\"\n", name);
3596 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3598 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3599 temp2 = temp1 + width * height * 4;
3600 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3601 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);
3604 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3605 if (textureflags & TEXF_ALPHA)
3607 for (i = 3;i < width * height * 4;i += 4)
3609 if (skindata[i] < 255)
3611 skinframe->hasalpha = true;
3615 if (r_loadfog && skinframe->hasalpha)
3617 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3618 memcpy(fogpixels, skindata, width * height * 4);
3619 for (i = 0;i < width * height * 4;i += 4)
3620 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3621 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3622 Mem_Free(fogpixels);
3626 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3627 //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]);
3632 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3636 skinframe_t *skinframe;
3638 if (cls.state == ca_dedicated)
3641 // if already loaded just return it, otherwise make a new skinframe
3642 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3643 if (skinframe->base)
3645 //textureflags &= ~TEXF_FORCE_RELOAD;
3647 skinframe->stain = NULL;
3648 skinframe->merged = NULL;
3649 skinframe->base = NULL;
3650 skinframe->pants = NULL;
3651 skinframe->shirt = NULL;
3652 skinframe->nmap = NULL;
3653 skinframe->gloss = NULL;
3654 skinframe->glow = NULL;
3655 skinframe->fog = NULL;
3656 skinframe->reflect = NULL;
3657 skinframe->hasalpha = false;
3659 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3663 if (developer_loading.integer)
3664 Con_Printf("loading quake skin \"%s\"\n", name);
3666 // 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)
3667 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3668 memcpy(skinframe->qpixels, skindata, width*height);
3669 skinframe->qwidth = width;
3670 skinframe->qheight = height;
3673 for (i = 0;i < width * height;i++)
3674 featuresmask |= palette_featureflags[skindata[i]];
3676 skinframe->hasalpha = false;
3677 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3678 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3679 skinframe->qgeneratemerged = true;
3680 skinframe->qgeneratebase = skinframe->qhascolormapping;
3681 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3683 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3684 //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]);
3689 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3693 unsigned char *skindata;
3696 if (!skinframe->qpixels)
3699 if (!skinframe->qhascolormapping)
3700 colormapped = false;
3704 if (!skinframe->qgeneratebase)
3709 if (!skinframe->qgeneratemerged)
3713 width = skinframe->qwidth;
3714 height = skinframe->qheight;
3715 skindata = skinframe->qpixels;
3717 if (skinframe->qgeneratenmap)
3719 unsigned char *temp1, *temp2;
3720 skinframe->qgeneratenmap = false;
3721 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3722 temp2 = temp1 + width * height * 4;
3723 // use either a custom palette or the quake palette
3724 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3725 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3726 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);
3730 if (skinframe->qgenerateglow)
3732 skinframe->qgenerateglow = false;
3733 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
3738 skinframe->qgeneratebase = false;
3739 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);
3740 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);
3741 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);
3745 skinframe->qgeneratemerged = false;
3746 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);
3749 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3751 Mem_Free(skinframe->qpixels);
3752 skinframe->qpixels = NULL;
3756 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)
3759 skinframe_t *skinframe;
3762 if (cls.state == ca_dedicated)
3765 // if already loaded just return it, otherwise make a new skinframe
3766 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3767 if (skinframe->base)
3769 textureflags &= ~TEXF_FORCE_RELOAD;
3771 skinframe->stain = NULL;
3772 skinframe->merged = NULL;
3773 skinframe->base = NULL;
3774 skinframe->pants = NULL;
3775 skinframe->shirt = NULL;
3776 skinframe->nmap = NULL;
3777 skinframe->gloss = NULL;
3778 skinframe->glow = NULL;
3779 skinframe->fog = NULL;
3780 skinframe->reflect = NULL;
3781 skinframe->hasalpha = false;
3783 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3787 if (developer_loading.integer)
3788 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3790 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3791 if (textureflags & TEXF_ALPHA)
3793 for (i = 0;i < width * height;i++)
3795 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3797 skinframe->hasalpha = true;
3801 if (r_loadfog && skinframe->hasalpha)
3802 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3805 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3806 //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]);
3811 skinframe_t *R_SkinFrame_LoadMissing(void)
3813 skinframe_t *skinframe;
3815 if (cls.state == ca_dedicated)
3818 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3819 skinframe->stain = NULL;
3820 skinframe->merged = NULL;
3821 skinframe->base = NULL;
3822 skinframe->pants = NULL;
3823 skinframe->shirt = NULL;
3824 skinframe->nmap = NULL;
3825 skinframe->gloss = NULL;
3826 skinframe->glow = NULL;
3827 skinframe->fog = NULL;
3828 skinframe->reflect = NULL;
3829 skinframe->hasalpha = false;
3831 skinframe->avgcolor[0] = rand() / RAND_MAX;
3832 skinframe->avgcolor[1] = rand() / RAND_MAX;
3833 skinframe->avgcolor[2] = rand() / RAND_MAX;
3834 skinframe->avgcolor[3] = 1;
3839 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3840 typedef struct suffixinfo_s
3843 qboolean flipx, flipy, flipdiagonal;
3846 static suffixinfo_t suffix[3][6] =
3849 {"px", false, false, false},
3850 {"nx", false, false, false},
3851 {"py", false, false, false},
3852 {"ny", false, false, false},
3853 {"pz", false, false, false},
3854 {"nz", false, false, false}
3857 {"posx", false, false, false},
3858 {"negx", false, false, false},
3859 {"posy", false, false, false},
3860 {"negy", false, false, false},
3861 {"posz", false, false, false},
3862 {"negz", false, false, false}
3865 {"rt", true, false, true},
3866 {"lf", false, true, true},
3867 {"ft", true, true, false},
3868 {"bk", false, false, false},
3869 {"up", true, false, true},
3870 {"dn", true, false, true}
3874 static int componentorder[4] = {0, 1, 2, 3};
3876 static rtexture_t *R_LoadCubemap(const char *basename)
3878 int i, j, cubemapsize;
3879 unsigned char *cubemappixels, *image_buffer;
3880 rtexture_t *cubemaptexture;
3882 // must start 0 so the first loadimagepixels has no requested width/height
3884 cubemappixels = NULL;
3885 cubemaptexture = NULL;
3886 // keep trying different suffix groups (posx, px, rt) until one loads
3887 for (j = 0;j < 3 && !cubemappixels;j++)
3889 // load the 6 images in the suffix group
3890 for (i = 0;i < 6;i++)
3892 // generate an image name based on the base and and suffix
3893 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3895 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3897 // an image loaded, make sure width and height are equal
3898 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3900 // if this is the first image to load successfully, allocate the cubemap memory
3901 if (!cubemappixels && image_width >= 1)
3903 cubemapsize = image_width;
3904 // note this clears to black, so unavailable sides are black
3905 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3907 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3909 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);
3912 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3914 Mem_Free(image_buffer);
3918 // if a cubemap loaded, upload it
3921 if (developer_loading.integer)
3922 Con_Printf("loading cubemap \"%s\"\n", basename);
3924 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);
3925 Mem_Free(cubemappixels);
3929 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3930 if (developer_loading.integer)
3932 Con_Printf("(tried tried images ");
3933 for (j = 0;j < 3;j++)
3934 for (i = 0;i < 6;i++)
3935 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3936 Con_Print(" and was unable to find any of them).\n");
3939 return cubemaptexture;
3942 rtexture_t *R_GetCubemap(const char *basename)
3945 for (i = 0;i < r_texture_numcubemaps;i++)
3946 if (r_texture_cubemaps[i] != NULL)
3947 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3948 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3949 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3950 return r_texture_whitecube;
3951 r_texture_numcubemaps++;
3952 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3953 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3954 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3955 return r_texture_cubemaps[i]->texture;
3958 static void R_Main_FreeViewCache(void)
3960 if (r_refdef.viewcache.entityvisible)
3961 Mem_Free(r_refdef.viewcache.entityvisible);
3962 if (r_refdef.viewcache.world_pvsbits)
3963 Mem_Free(r_refdef.viewcache.world_pvsbits);
3964 if (r_refdef.viewcache.world_leafvisible)
3965 Mem_Free(r_refdef.viewcache.world_leafvisible);
3966 if (r_refdef.viewcache.world_surfacevisible)
3967 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3968 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3971 static void R_Main_ResizeViewCache(void)
3973 int numentities = r_refdef.scene.numentities;
3974 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3975 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3976 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3977 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3978 if (r_refdef.viewcache.maxentities < numentities)
3980 r_refdef.viewcache.maxentities = numentities;
3981 if (r_refdef.viewcache.entityvisible)
3982 Mem_Free(r_refdef.viewcache.entityvisible);
3983 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3985 if (r_refdef.viewcache.world_numclusters != numclusters)
3987 r_refdef.viewcache.world_numclusters = numclusters;
3988 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3989 if (r_refdef.viewcache.world_pvsbits)
3990 Mem_Free(r_refdef.viewcache.world_pvsbits);
3991 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3993 if (r_refdef.viewcache.world_numleafs != numleafs)
3995 r_refdef.viewcache.world_numleafs = numleafs;
3996 if (r_refdef.viewcache.world_leafvisible)
3997 Mem_Free(r_refdef.viewcache.world_leafvisible);
3998 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4000 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4002 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4003 if (r_refdef.viewcache.world_surfacevisible)
4004 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4005 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4009 extern rtexture_t *loadingscreentexture;
4010 static void gl_main_start(void)
4012 loadingscreentexture = NULL;
4013 r_texture_blanknormalmap = NULL;
4014 r_texture_white = NULL;
4015 r_texture_grey128 = NULL;
4016 r_texture_black = NULL;
4017 r_texture_whitecube = NULL;
4018 r_texture_normalizationcube = NULL;
4019 r_texture_fogattenuation = NULL;
4020 r_texture_fogheighttexture = NULL;
4021 r_texture_gammaramps = NULL;
4022 r_texture_numcubemaps = 0;
4023 r_uniformbufferalignment = 32;
4025 r_loaddds = r_texture_dds_load.integer != 0;
4026 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4028 switch(vid.renderpath)
4030 case RENDERPATH_GL20:
4031 case RENDERPATH_D3D9:
4032 case RENDERPATH_D3D10:
4033 case RENDERPATH_D3D11:
4034 case RENDERPATH_SOFT:
4035 case RENDERPATH_GLES2:
4036 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4037 Cvar_SetValueQuick(&gl_combine, 1);
4038 Cvar_SetValueQuick(&r_glsl, 1);
4039 r_loadnormalmap = true;
4042 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4043 if (vid.support.arb_uniform_buffer_object)
4044 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4047 case RENDERPATH_GL13:
4048 case RENDERPATH_GLES1:
4049 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4050 Cvar_SetValueQuick(&gl_combine, 1);
4051 Cvar_SetValueQuick(&r_glsl, 0);
4052 r_loadnormalmap = false;
4053 r_loadgloss = false;
4056 case RENDERPATH_GL11:
4057 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4058 Cvar_SetValueQuick(&gl_combine, 0);
4059 Cvar_SetValueQuick(&r_glsl, 0);
4060 r_loadnormalmap = false;
4061 r_loadgloss = false;
4067 R_FrameData_Reset();
4068 R_BufferData_Reset();
4072 memset(r_queries, 0, sizeof(r_queries));
4074 r_qwskincache = NULL;
4075 r_qwskincache_size = 0;
4077 // due to caching of texture_t references, the collision cache must be reset
4078 Collision_Cache_Reset(true);
4080 // set up r_skinframe loading system for textures
4081 memset(&r_skinframe, 0, sizeof(r_skinframe));
4082 r_skinframe.loadsequence = 1;
4083 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4085 r_main_texturepool = R_AllocTexturePool();
4086 R_BuildBlankTextures();
4088 if (vid.support.arb_texture_cube_map)
4091 R_BuildNormalizationCube();
4093 r_texture_fogattenuation = NULL;
4094 r_texture_fogheighttexture = NULL;
4095 r_texture_gammaramps = NULL;
4096 //r_texture_fogintensity = NULL;
4097 memset(&r_fb, 0, sizeof(r_fb));
4098 r_glsl_permutation = NULL;
4099 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4100 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4101 glslshaderstring = NULL;
4103 r_hlsl_permutation = NULL;
4104 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4105 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4107 hlslshaderstring = NULL;
4108 memset(&r_svbsp, 0, sizeof (r_svbsp));
4110 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4111 r_texture_numcubemaps = 0;
4113 r_refdef.fogmasktable_density = 0;
4116 // For Steelstorm Android
4117 // FIXME CACHE the program and reload
4118 // FIXME see possible combinations for SS:BR android
4119 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4120 R_SetupShader_SetPermutationGLSL(0, 12);
4121 R_SetupShader_SetPermutationGLSL(0, 13);
4122 R_SetupShader_SetPermutationGLSL(0, 8388621);
4123 R_SetupShader_SetPermutationGLSL(3, 0);
4124 R_SetupShader_SetPermutationGLSL(3, 2048);
4125 R_SetupShader_SetPermutationGLSL(5, 0);
4126 R_SetupShader_SetPermutationGLSL(5, 2);
4127 R_SetupShader_SetPermutationGLSL(5, 2048);
4128 R_SetupShader_SetPermutationGLSL(5, 8388608);
4129 R_SetupShader_SetPermutationGLSL(11, 1);
4130 R_SetupShader_SetPermutationGLSL(11, 2049);
4131 R_SetupShader_SetPermutationGLSL(11, 8193);
4132 R_SetupShader_SetPermutationGLSL(11, 10241);
4133 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4137 static void gl_main_shutdown(void)
4140 R_FrameData_Reset();
4141 R_BufferData_Reset();
4143 R_Main_FreeViewCache();
4145 switch(vid.renderpath)
4147 case RENDERPATH_GL11:
4148 case RENDERPATH_GL13:
4149 case RENDERPATH_GL20:
4150 case RENDERPATH_GLES1:
4151 case RENDERPATH_GLES2:
4152 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4154 qglDeleteQueriesARB(r_maxqueries, r_queries);
4157 case RENDERPATH_D3D9:
4158 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4160 case RENDERPATH_D3D10:
4161 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4163 case RENDERPATH_D3D11:
4164 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4166 case RENDERPATH_SOFT:
4172 memset(r_queries, 0, sizeof(r_queries));
4174 r_qwskincache = NULL;
4175 r_qwskincache_size = 0;
4177 // clear out the r_skinframe state
4178 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4179 memset(&r_skinframe, 0, sizeof(r_skinframe));
4182 Mem_Free(r_svbsp.nodes);
4183 memset(&r_svbsp, 0, sizeof (r_svbsp));
4184 R_FreeTexturePool(&r_main_texturepool);
4185 loadingscreentexture = NULL;
4186 r_texture_blanknormalmap = NULL;
4187 r_texture_white = NULL;
4188 r_texture_grey128 = NULL;
4189 r_texture_black = NULL;
4190 r_texture_whitecube = NULL;
4191 r_texture_normalizationcube = NULL;
4192 r_texture_fogattenuation = NULL;
4193 r_texture_fogheighttexture = NULL;
4194 r_texture_gammaramps = NULL;
4195 r_texture_numcubemaps = 0;
4196 //r_texture_fogintensity = NULL;
4197 memset(&r_fb, 0, sizeof(r_fb));
4200 r_glsl_permutation = NULL;
4201 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4202 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4203 glslshaderstring = NULL;
4205 r_hlsl_permutation = NULL;
4206 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4207 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4209 hlslshaderstring = NULL;
4212 static void gl_main_newmap(void)
4214 // FIXME: move this code to client
4215 char *entities, entname[MAX_QPATH];
4217 Mem_Free(r_qwskincache);
4218 r_qwskincache = NULL;
4219 r_qwskincache_size = 0;
4222 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4223 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4225 CL_ParseEntityLump(entities);
4229 if (cl.worldmodel->brush.entities)
4230 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4232 R_Main_FreeViewCache();
4234 R_FrameData_Reset();
4235 R_BufferData_Reset();
4238 void GL_Main_Init(void)
4241 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4243 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4244 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4245 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4246 if (gamemode == GAME_NEHAHRA)
4248 Cvar_RegisterVariable (&gl_fogenable);
4249 Cvar_RegisterVariable (&gl_fogdensity);
4250 Cvar_RegisterVariable (&gl_fogred);
4251 Cvar_RegisterVariable (&gl_foggreen);
4252 Cvar_RegisterVariable (&gl_fogblue);
4253 Cvar_RegisterVariable (&gl_fogstart);
4254 Cvar_RegisterVariable (&gl_fogend);
4255 Cvar_RegisterVariable (&gl_skyclip);
4257 Cvar_RegisterVariable(&r_motionblur);
4258 Cvar_RegisterVariable(&r_damageblur);
4259 Cvar_RegisterVariable(&r_motionblur_averaging);
4260 Cvar_RegisterVariable(&r_motionblur_randomize);
4261 Cvar_RegisterVariable(&r_motionblur_minblur);
4262 Cvar_RegisterVariable(&r_motionblur_maxblur);
4263 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4264 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4265 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4266 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4267 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4268 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4269 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4270 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4271 Cvar_RegisterVariable(&r_equalize_entities_by);
4272 Cvar_RegisterVariable(&r_equalize_entities_to);
4273 Cvar_RegisterVariable(&r_depthfirst);
4274 Cvar_RegisterVariable(&r_useinfinitefarclip);
4275 Cvar_RegisterVariable(&r_farclip_base);
4276 Cvar_RegisterVariable(&r_farclip_world);
4277 Cvar_RegisterVariable(&r_nearclip);
4278 Cvar_RegisterVariable(&r_deformvertexes);
4279 Cvar_RegisterVariable(&r_transparent);
4280 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4281 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4282 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4283 Cvar_RegisterVariable(&r_showoverdraw);
4284 Cvar_RegisterVariable(&r_showbboxes);
4285 Cvar_RegisterVariable(&r_showsurfaces);
4286 Cvar_RegisterVariable(&r_showtris);
4287 Cvar_RegisterVariable(&r_shownormals);
4288 Cvar_RegisterVariable(&r_showlighting);
4289 Cvar_RegisterVariable(&r_showshadowvolumes);
4290 Cvar_RegisterVariable(&r_showcollisionbrushes);
4291 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4292 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4293 Cvar_RegisterVariable(&r_showdisabledepthtest);
4294 Cvar_RegisterVariable(&r_drawportals);
4295 Cvar_RegisterVariable(&r_drawentities);
4296 Cvar_RegisterVariable(&r_draw2d);
4297 Cvar_RegisterVariable(&r_drawworld);
4298 Cvar_RegisterVariable(&r_cullentities_trace);
4299 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4300 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4301 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4302 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4303 Cvar_RegisterVariable(&r_sortentities);
4304 Cvar_RegisterVariable(&r_drawviewmodel);
4305 Cvar_RegisterVariable(&r_drawexteriormodel);
4306 Cvar_RegisterVariable(&r_speeds);
4307 Cvar_RegisterVariable(&r_fullbrights);
4308 Cvar_RegisterVariable(&r_wateralpha);
4309 Cvar_RegisterVariable(&r_dynamic);
4310 Cvar_RegisterVariable(&r_fakelight);
4311 Cvar_RegisterVariable(&r_fakelight_intensity);
4312 Cvar_RegisterVariable(&r_fullbright);
4313 Cvar_RegisterVariable(&r_shadows);
4314 Cvar_RegisterVariable(&r_shadows_darken);
4315 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4316 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4317 Cvar_RegisterVariable(&r_shadows_throwdistance);
4318 Cvar_RegisterVariable(&r_shadows_throwdirection);
4319 Cvar_RegisterVariable(&r_shadows_focus);
4320 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4321 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4322 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4323 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4324 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4325 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4326 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4327 Cvar_RegisterVariable(&r_fog_exp2);
4328 Cvar_RegisterVariable(&r_fog_clear);
4329 Cvar_RegisterVariable(&r_drawfog);
4330 Cvar_RegisterVariable(&r_transparentdepthmasking);
4331 Cvar_RegisterVariable(&r_transparent_sortmindist);
4332 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4333 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4334 Cvar_RegisterVariable(&r_texture_dds_load);
4335 Cvar_RegisterVariable(&r_texture_dds_save);
4336 Cvar_RegisterVariable(&r_textureunits);
4337 Cvar_RegisterVariable(&gl_combine);
4338 Cvar_RegisterVariable(&r_usedepthtextures);
4339 Cvar_RegisterVariable(&r_viewfbo);
4340 Cvar_RegisterVariable(&r_viewscale);
4341 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4342 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4343 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4344 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4345 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4346 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4347 Cvar_RegisterVariable(&r_glsl);
4348 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4349 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4350 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4351 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4352 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4353 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4354 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4355 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4356 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4357 Cvar_RegisterVariable(&r_glsl_postprocess);
4358 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4359 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4360 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4361 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4362 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4363 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4364 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4365 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4366 Cvar_RegisterVariable(&r_celshading);
4367 Cvar_RegisterVariable(&r_celoutlines);
4369 Cvar_RegisterVariable(&r_water);
4370 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4371 Cvar_RegisterVariable(&r_water_clippingplanebias);
4372 Cvar_RegisterVariable(&r_water_refractdistort);
4373 Cvar_RegisterVariable(&r_water_reflectdistort);
4374 Cvar_RegisterVariable(&r_water_scissormode);
4375 Cvar_RegisterVariable(&r_water_lowquality);
4376 Cvar_RegisterVariable(&r_water_hideplayer);
4377 Cvar_RegisterVariable(&r_water_fbo);
4379 Cvar_RegisterVariable(&r_lerpsprites);
4380 Cvar_RegisterVariable(&r_lerpmodels);
4381 Cvar_RegisterVariable(&r_lerplightstyles);
4382 Cvar_RegisterVariable(&r_waterscroll);
4383 Cvar_RegisterVariable(&r_bloom);
4384 Cvar_RegisterVariable(&r_bloom_colorscale);
4385 Cvar_RegisterVariable(&r_bloom_brighten);
4386 Cvar_RegisterVariable(&r_bloom_blur);
4387 Cvar_RegisterVariable(&r_bloom_resolution);
4388 Cvar_RegisterVariable(&r_bloom_colorexponent);
4389 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4390 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4391 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4392 Cvar_RegisterVariable(&r_hdr_glowintensity);
4393 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4394 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4395 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4396 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4397 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4398 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4399 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4400 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4401 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4402 Cvar_RegisterVariable(&developer_texturelogging);
4403 Cvar_RegisterVariable(&gl_lightmaps);
4404 Cvar_RegisterVariable(&r_test);
4405 Cvar_RegisterVariable(&r_batch_multidraw);
4406 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4407 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4408 Cvar_RegisterVariable(&r_glsl_skeletal);
4409 Cvar_RegisterVariable(&r_glsl_saturation);
4410 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4411 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4412 Cvar_RegisterVariable(&r_framedatasize);
4413 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4414 Cvar_RegisterVariable(&r_buffermegs[i]);
4415 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4416 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4417 Cvar_SetValue("r_fullbrights", 0);
4418 #ifdef DP_MOBILETOUCH
4419 // GLES devices have terrible depth precision in general, so...
4420 Cvar_SetValueQuick(&r_nearclip, 4);
4421 Cvar_SetValueQuick(&r_farclip_base, 4096);
4422 Cvar_SetValueQuick(&r_farclip_world, 0);
4423 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4425 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4428 void Render_Init(void)
4441 R_LightningBeams_Init();
4451 extern char *ENGINE_EXTENSIONS;
4454 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4455 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4456 gl_version = (const char *)qglGetString(GL_VERSION);
4457 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4461 if (!gl_platformextensions)
4462 gl_platformextensions = "";
4464 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4465 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4466 Con_Printf("GL_VERSION: %s\n", gl_version);
4467 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4468 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4470 VID_CheckExtensions();
4472 // LordHavoc: report supported extensions
4474 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4476 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4479 // clear to black (loading plaque will be seen over this)
4480 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4484 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4488 if (r_trippy.integer)
4490 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4492 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4495 p = r_refdef.view.frustum + i;
4500 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4504 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4508 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4512 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4516 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4520 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4524 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4528 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4536 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4540 if (r_trippy.integer)
4542 for (i = 0;i < numplanes;i++)
4549 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4553 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4557 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4561 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4565 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4569 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4573 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4577 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4585 //==================================================================================
4587 // LordHavoc: this stores temporary data used within the same frame
4589 typedef struct r_framedata_mem_s
4591 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4592 size_t size; // how much usable space
4593 size_t current; // how much space in use
4594 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4595 size_t wantedsize; // how much space was allocated
4596 unsigned char *data; // start of real data (16byte aligned)
4600 static r_framedata_mem_t *r_framedata_mem;
4602 void R_FrameData_Reset(void)
4604 while (r_framedata_mem)
4606 r_framedata_mem_t *next = r_framedata_mem->purge;
4607 Mem_Free(r_framedata_mem);
4608 r_framedata_mem = next;
4612 static void R_FrameData_Resize(qboolean mustgrow)
4615 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4616 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4617 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4619 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4620 newmem->wantedsize = wantedsize;
4621 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4622 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4623 newmem->current = 0;
4625 newmem->purge = r_framedata_mem;
4626 r_framedata_mem = newmem;
4630 void R_FrameData_NewFrame(void)
4632 R_FrameData_Resize(false);
4633 if (!r_framedata_mem)
4635 // if we ran out of space on the last frame, free the old memory now
4636 while (r_framedata_mem->purge)
4638 // repeatedly remove the second item in the list, leaving only head
4639 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4640 Mem_Free(r_framedata_mem->purge);
4641 r_framedata_mem->purge = next;
4643 // reset the current mem pointer
4644 r_framedata_mem->current = 0;
4645 r_framedata_mem->mark = 0;
4648 void *R_FrameData_Alloc(size_t size)
4653 // align to 16 byte boundary - the data pointer is already aligned, so we
4654 // only need to ensure the size of every allocation is also aligned
4655 size = (size + 15) & ~15;
4657 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4659 // emergency - we ran out of space, allocate more memory
4660 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4661 // this might not be a growing it, but we'll allocate another buffer every time
4662 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4663 R_FrameData_Resize(true);
4666 data = r_framedata_mem->data + r_framedata_mem->current;
4667 r_framedata_mem->current += size;
4669 // count the usage for stats
4670 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4671 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4673 return (void *)data;
4676 void *R_FrameData_Store(size_t size, void *data)
4678 void *d = R_FrameData_Alloc(size);
4680 memcpy(d, data, size);
4684 void R_FrameData_SetMark(void)
4686 if (!r_framedata_mem)
4688 r_framedata_mem->mark = r_framedata_mem->current;
4691 void R_FrameData_ReturnToMark(void)
4693 if (!r_framedata_mem)
4695 r_framedata_mem->current = r_framedata_mem->mark;
4698 //==================================================================================
4700 // avoid reusing the same buffer objects on consecutive frames
4701 #define R_BUFFERDATA_CYCLE 3
4703 typedef struct r_bufferdata_buffer_s
4705 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4706 size_t size; // how much usable space
4707 size_t current; // how much space in use
4708 r_meshbuffer_t *buffer; // the buffer itself
4710 r_bufferdata_buffer_t;
4712 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4713 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4715 /// frees all dynamic buffers
4716 void R_BufferData_Reset(void)
4719 r_bufferdata_buffer_t **p, *mem;
4720 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4722 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4725 p = &r_bufferdata_buffer[cycle][type];
4731 R_Mesh_DestroyMeshBuffer(mem->buffer);
4738 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4739 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4741 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4743 float newvalue = r_buffermegs[type].value;
4745 // increase the cvar if we have to (but only if we already have a mem)
4746 if (mustgrow && mem)
4748 newvalue = bound(0.25f, newvalue, 256.0f);
4749 while (newvalue * 1024*1024 < minsize)
4752 // clamp the cvar to valid range
4753 newvalue = bound(0.25f, newvalue, 256.0f);
4754 if (r_buffermegs[type].value != newvalue)
4755 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4757 // calculate size in bytes
4758 size = (size_t)(newvalue * 1024*1024);
4759 size = bound(131072, size, 256*1024*1024);
4761 // allocate a new buffer if the size is different (purge old one later)
4762 // or if we were told we must grow the buffer
4763 if (!mem || mem->size != size || mustgrow)
4765 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4768 if (type == R_BUFFERDATA_VERTEX)
4769 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4770 else if (type == R_BUFFERDATA_INDEX16)
4771 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4772 else if (type == R_BUFFERDATA_INDEX32)
4773 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4774 else if (type == R_BUFFERDATA_UNIFORM)
4775 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4776 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4777 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4781 void R_BufferData_NewFrame(void)
4784 r_bufferdata_buffer_t **p, *mem;
4785 // cycle to the next frame's buffers
4786 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4787 // if we ran out of space on the last time we used these buffers, free the old memory now
4788 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4790 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4792 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4793 // free all but the head buffer, this is how we recycle obsolete
4794 // buffers after they are no longer in use
4795 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4801 R_Mesh_DestroyMeshBuffer(mem->buffer);
4804 // reset the current offset
4805 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4810 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4812 r_bufferdata_buffer_t *mem;
4816 *returnbufferoffset = 0;
4818 // align size to a byte boundary appropriate for the buffer type, this
4819 // makes all allocations have aligned start offsets
4820 if (type == R_BUFFERDATA_UNIFORM)
4821 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4823 padsize = (datasize + 15) & ~15;
4825 // if we ran out of space in this buffer we must allocate a new one
4826 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4827 R_BufferData_Resize(type, true, padsize);
4829 // if the resize did not give us enough memory, fail
4830 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4831 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4833 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4834 offset = mem->current;
4835 mem->current += padsize;
4837 // upload the data to the buffer at the chosen offset
4839 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4840 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4842 // count the usage for stats
4843 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4844 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4846 // return the buffer offset
4847 *returnbufferoffset = offset;
4852 //==================================================================================
4854 // LordHavoc: animcache originally written by Echon, rewritten since then
4857 * Animation cache prevents re-generating mesh data for an animated model
4858 * multiple times in one frame for lighting, shadowing, reflections, etc.
4861 void R_AnimCache_Free(void)
4865 void R_AnimCache_ClearCache(void)
4868 entity_render_t *ent;
4870 for (i = 0;i < r_refdef.scene.numentities;i++)
4872 ent = r_refdef.scene.entities[i];
4873 ent->animcache_vertex3f = NULL;
4874 ent->animcache_vertex3f_vertexbuffer = NULL;
4875 ent->animcache_vertex3f_bufferoffset = 0;
4876 ent->animcache_normal3f = NULL;
4877 ent->animcache_normal3f_vertexbuffer = NULL;
4878 ent->animcache_normal3f_bufferoffset = 0;
4879 ent->animcache_svector3f = NULL;
4880 ent->animcache_svector3f_vertexbuffer = NULL;
4881 ent->animcache_svector3f_bufferoffset = 0;
4882 ent->animcache_tvector3f = NULL;
4883 ent->animcache_tvector3f_vertexbuffer = NULL;
4884 ent->animcache_tvector3f_bufferoffset = 0;
4885 ent->animcache_vertexmesh = NULL;
4886 ent->animcache_vertexmesh_vertexbuffer = NULL;
4887 ent->animcache_vertexmesh_bufferoffset = 0;
4888 ent->animcache_skeletaltransform3x4 = NULL;
4889 ent->animcache_skeletaltransform3x4buffer = NULL;
4890 ent->animcache_skeletaltransform3x4offset = 0;
4891 ent->animcache_skeletaltransform3x4size = 0;
4895 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4899 // check if we need the meshbuffers
4900 if (!vid.useinterleavedarrays)
4903 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4904 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4905 // TODO: upload vertexbuffer?
4906 if (ent->animcache_vertexmesh)
4908 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4909 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4910 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4911 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4912 for (i = 0;i < numvertices;i++)
4913 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4914 if (ent->animcache_svector3f)
4915 for (i = 0;i < numvertices;i++)
4916 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4917 if (ent->animcache_tvector3f)
4918 for (i = 0;i < numvertices;i++)
4919 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4920 if (ent->animcache_normal3f)
4921 for (i = 0;i < numvertices;i++)
4922 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4926 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4928 dp_model_t *model = ent->model;
4931 // see if this ent is worth caching
4932 if (!model || !model->Draw || !model->AnimateVertices)
4934 // nothing to cache if it contains no animations and has no skeleton
4935 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4937 // see if it is already cached for gpuskeletal
4938 if (ent->animcache_skeletaltransform3x4)
4940 // see if it is already cached as a mesh
4941 if (ent->animcache_vertex3f)
4943 // check if we need to add normals or tangents
4944 if (ent->animcache_normal3f)
4945 wantnormals = false;
4946 if (ent->animcache_svector3f)
4947 wanttangents = false;
4948 if (!wantnormals && !wanttangents)
4952 // check which kind of cache we need to generate
4953 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4955 // cache the skeleton so the vertex shader can use it
4956 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4957 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4958 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4959 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4960 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4961 // note: this can fail if the buffer is at the grow limit
4962 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4963 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4965 else if (ent->animcache_vertex3f)
4967 // mesh was already cached but we may need to add normals/tangents
4968 // (this only happens with multiple views, reflections, cameras, etc)
4969 if (wantnormals || wanttangents)
4971 numvertices = model->surfmesh.num_vertices;
4973 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4976 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4977 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4979 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4980 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4981 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4982 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4983 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4988 // generate mesh cache
4989 numvertices = model->surfmesh.num_vertices;
4990 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4992 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4995 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4996 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4998 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4999 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5000 if (wantnormals || wanttangents)
5002 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5003 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5004 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5006 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5007 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5008 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5013 void R_AnimCache_CacheVisibleEntities(void)
5016 qboolean wantnormals = true;
5017 qboolean wanttangents = !r_showsurfaces.integer;
5019 switch(vid.renderpath)
5021 case RENDERPATH_GL20:
5022 case RENDERPATH_D3D9:
5023 case RENDERPATH_D3D10:
5024 case RENDERPATH_D3D11:
5025 case RENDERPATH_GLES2:
5027 case RENDERPATH_GL11:
5028 case RENDERPATH_GL13:
5029 case RENDERPATH_GLES1:
5030 wanttangents = false;
5032 case RENDERPATH_SOFT:
5036 if (r_shownormals.integer)
5037 wanttangents = wantnormals = true;
5039 // TODO: thread this
5040 // NOTE: R_PrepareRTLights() also caches entities
5042 for (i = 0;i < r_refdef.scene.numentities;i++)
5043 if (r_refdef.viewcache.entityvisible[i])
5044 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5047 //==================================================================================
5049 extern cvar_t r_overheadsprites_pushback;
5051 static void R_View_UpdateEntityLighting (void)
5054 entity_render_t *ent;
5055 vec3_t tempdiffusenormal, avg;
5056 vec_t f, fa, fd, fdd;
5057 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5059 for (i = 0;i < r_refdef.scene.numentities;i++)
5061 ent = r_refdef.scene.entities[i];
5063 // skip unseen models
5064 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5068 if (ent->model && ent->model == cl.worldmodel)
5070 // TODO: use modellight for r_ambient settings on world?
5071 VectorSet(ent->modellight_ambient, 0, 0, 0);
5072 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5073 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5077 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5079 // aleady updated by CSQC
5080 // TODO: force modellight on BSP models in this case?
5081 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5085 // fetch the lighting from the worldmodel data
5086 VectorClear(ent->modellight_ambient);
5087 VectorClear(ent->modellight_diffuse);
5088 VectorClear(tempdiffusenormal);
5089 if (ent->flags & RENDER_LIGHT)
5092 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5094 // complete lightning for lit sprites
5095 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5096 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5098 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5099 org[2] = org[2] + r_overheadsprites_pushback.value;
5100 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5103 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5105 if(ent->flags & RENDER_EQUALIZE)
5107 // first fix up ambient lighting...
5108 if(r_equalize_entities_minambient.value > 0)
5110 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5113 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5114 if(fa < r_equalize_entities_minambient.value * fd)
5117 // fa'/fd' = minambient
5118 // fa'+0.25*fd' = fa+0.25*fd
5120 // fa' = fd' * minambient
5121 // fd'*(0.25+minambient) = fa+0.25*fd
5123 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5124 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5126 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5127 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
5128 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5129 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5134 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5136 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5137 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5141 // adjust brightness and saturation to target
5142 avg[0] = avg[1] = avg[2] = fa / f;
5143 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5144 avg[0] = avg[1] = avg[2] = fd / f;
5145 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5151 VectorSet(ent->modellight_ambient, 1, 1, 1);
5154 // move the light direction into modelspace coordinates for lighting code
5155 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5156 if(VectorLength2(ent->modellight_lightdir) == 0)
5157 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5158 VectorNormalize(ent->modellight_lightdir);
5162 #define MAX_LINEOFSIGHTTRACES 64
5164 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5167 vec3_t boxmins, boxmaxs;
5170 dp_model_t *model = r_refdef.scene.worldmodel;
5172 if (!model || !model->brush.TraceLineOfSight)
5175 // expand the box a little
5176 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5177 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5178 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5179 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5180 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5181 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5183 // return true if eye is inside enlarged box
5184 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5188 VectorCopy(eye, start);
5189 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5190 if (model->brush.TraceLineOfSight(model, start, end))
5193 // try various random positions
5194 for (i = 0;i < numsamples;i++)
5196 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5197 if (model->brush.TraceLineOfSight(model, start, end))
5205 static void R_View_UpdateEntityVisible (void)
5210 entity_render_t *ent;
5212 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5213 : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5214 : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL
5215 : RENDER_EXTERIORMODEL;
5216 if (!r_drawviewmodel.integer)
5217 renderimask |= RENDER_VIEWMODEL;
5218 if (!r_drawexteriormodel.integer)
5219 renderimask |= RENDER_EXTERIORMODEL;
5220 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5222 // worldmodel can check visibility
5223 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5224 for (i = 0;i < r_refdef.scene.numentities;i++)
5226 ent = r_refdef.scene.entities[i];
5227 if (!(ent->flags & renderimask))
5228 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)))
5229 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))
5230 r_refdef.viewcache.entityvisible[i] = true;
5235 // no worldmodel or it can't check visibility
5236 for (i = 0;i < r_refdef.scene.numentities;i++)
5238 ent = r_refdef.scene.entities[i];
5239 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));
5242 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5243 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5245 for (i = 0;i < r_refdef.scene.numentities;i++)
5247 if (!r_refdef.viewcache.entityvisible[i])
5249 ent = r_refdef.scene.entities[i];
5250 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5252 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5254 continue; // temp entities do pvs only
5255 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5256 ent->last_trace_visibility = realtime;
5257 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5258 r_refdef.viewcache.entityvisible[i] = 0;
5264 /// only used if skyrendermasked, and normally returns false
5265 static int R_DrawBrushModelsSky (void)
5268 entity_render_t *ent;
5271 for (i = 0;i < r_refdef.scene.numentities;i++)
5273 if (!r_refdef.viewcache.entityvisible[i])
5275 ent = r_refdef.scene.entities[i];
5276 if (!ent->model || !ent->model->DrawSky)
5278 ent->model->DrawSky(ent);
5284 static void R_DrawNoModel(entity_render_t *ent);
5285 static void R_DrawModels(void)
5288 entity_render_t *ent;
5290 for (i = 0;i < r_refdef.scene.numentities;i++)
5292 if (!r_refdef.viewcache.entityvisible[i])
5294 ent = r_refdef.scene.entities[i];
5295 r_refdef.stats[r_stat_entities]++;
5297 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5300 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5301 Con_Printf("R_DrawModels\n");
5302 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]);
5303 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);
5304 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);
5307 if (ent->model && ent->model->Draw != NULL)
5308 ent->model->Draw(ent);
5314 static void R_DrawModelsDepth(void)
5317 entity_render_t *ent;
5319 for (i = 0;i < r_refdef.scene.numentities;i++)
5321 if (!r_refdef.viewcache.entityvisible[i])
5323 ent = r_refdef.scene.entities[i];
5324 if (ent->model && ent->model->DrawDepth != NULL)
5325 ent->model->DrawDepth(ent);
5329 static void R_DrawModelsDebug(void)
5332 entity_render_t *ent;
5334 for (i = 0;i < r_refdef.scene.numentities;i++)
5336 if (!r_refdef.viewcache.entityvisible[i])
5338 ent = r_refdef.scene.entities[i];
5339 if (ent->model && ent->model->DrawDebug != NULL)
5340 ent->model->DrawDebug(ent);
5344 static void R_DrawModelsAddWaterPlanes(void)
5347 entity_render_t *ent;
5349 for (i = 0;i < r_refdef.scene.numentities;i++)
5351 if (!r_refdef.viewcache.entityvisible[i])
5353 ent = r_refdef.scene.entities[i];
5354 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5355 ent->model->DrawAddWaterPlanes(ent);
5359 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}};
5361 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5363 if (r_hdr_irisadaptation.integer)
5368 vec3_t diffusenormal;
5370 vec_t brightness = 0.0f;
5375 VectorCopy(r_refdef.view.forward, forward);
5376 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5378 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5379 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5380 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5381 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5382 d = DotProduct(forward, diffusenormal);
5383 brightness += VectorLength(ambient);
5385 brightness += d * VectorLength(diffuse);
5387 brightness *= 1.0f / c;
5388 brightness += 0.00001f; // make sure it's never zero
5389 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5390 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5391 current = r_hdr_irisadaptation_value.value;
5393 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5394 else if (current > goal)
5395 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5396 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5397 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5399 else if (r_hdr_irisadaptation_value.value != 1.0f)
5400 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5403 static void R_View_SetFrustum(const int *scissor)
5406 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5407 vec3_t forward, left, up, origin, v;
5411 // flipped x coordinates (because x points left here)
5412 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5413 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5415 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5416 switch(vid.renderpath)
5418 case RENDERPATH_D3D9:
5419 case RENDERPATH_D3D10:
5420 case RENDERPATH_D3D11:
5421 // non-flipped y coordinates
5422 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5423 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5425 case RENDERPATH_SOFT:
5426 case RENDERPATH_GL11:
5427 case RENDERPATH_GL13:
5428 case RENDERPATH_GL20:
5429 case RENDERPATH_GLES1:
5430 case RENDERPATH_GLES2:
5431 // non-flipped y coordinates
5432 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5433 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5438 // we can't trust r_refdef.view.forward and friends in reflected scenes
5439 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5442 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5443 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5444 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5445 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5446 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5447 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5448 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5449 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5450 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5451 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5452 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5453 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5457 zNear = r_refdef.nearclip;
5458 nudge = 1.0 - 1.0 / (1<<23);
5459 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5460 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5461 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5462 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5463 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5464 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5465 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5466 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5472 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5473 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5474 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5475 r_refdef.view.frustum[0].dist = m[15] - m[12];
5477 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5478 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5479 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5480 r_refdef.view.frustum[1].dist = m[15] + m[12];
5482 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5483 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5484 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5485 r_refdef.view.frustum[2].dist = m[15] - m[13];
5487 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5488 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5489 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5490 r_refdef.view.frustum[3].dist = m[15] + m[13];
5492 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5493 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5494 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5495 r_refdef.view.frustum[4].dist = m[15] - m[14];
5497 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5498 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5499 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5500 r_refdef.view.frustum[5].dist = m[15] + m[14];
5503 if (r_refdef.view.useperspective)
5505 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5506 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]);
5507 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]);
5508 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]);
5509 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]);
5511 // then the normals from the corners relative to origin
5512 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5513 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5514 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5515 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5517 // in a NORMAL view, forward cross left == up
5518 // in a REFLECTED view, forward cross left == down
5519 // so our cross products above need to be adjusted for a left handed coordinate system
5520 CrossProduct(forward, left, v);
5521 if(DotProduct(v, up) < 0)
5523 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5524 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5525 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5526 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5529 // Leaving those out was a mistake, those were in the old code, and they
5530 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5531 // I couldn't reproduce it after adding those normalizations. --blub
5532 VectorNormalize(r_refdef.view.frustum[0].normal);
5533 VectorNormalize(r_refdef.view.frustum[1].normal);
5534 VectorNormalize(r_refdef.view.frustum[2].normal);
5535 VectorNormalize(r_refdef.view.frustum[3].normal);
5537 // make the corners absolute
5538 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5539 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5540 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5541 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5544 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5546 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5547 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5548 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5549 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5550 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5554 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5555 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5556 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5557 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5558 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5559 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5560 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5561 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5562 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5563 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5565 r_refdef.view.numfrustumplanes = 5;
5567 if (r_refdef.view.useclipplane)
5569 r_refdef.view.numfrustumplanes = 6;
5570 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5573 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5574 PlaneClassify(r_refdef.view.frustum + i);
5576 // LordHavoc: note to all quake engine coders, Quake had a special case
5577 // for 90 degrees which assumed a square view (wrong), so I removed it,
5578 // Quake2 has it disabled as well.
5580 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5581 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5582 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5583 //PlaneClassify(&frustum[0]);
5585 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5586 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5587 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5588 //PlaneClassify(&frustum[1]);
5590 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5591 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5592 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5593 //PlaneClassify(&frustum[2]);
5595 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5596 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5597 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5598 //PlaneClassify(&frustum[3]);
5601 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5602 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5603 //PlaneClassify(&frustum[4]);
5606 static void R_View_UpdateWithScissor(const int *myscissor)
5608 R_Main_ResizeViewCache();
5609 R_View_SetFrustum(myscissor);
5610 R_View_WorldVisibility(r_refdef.view.useclipplane);
5611 R_View_UpdateEntityVisible();
5612 R_View_UpdateEntityLighting();
5615 static void R_View_Update(void)
5617 R_Main_ResizeViewCache();
5618 R_View_SetFrustum(NULL);
5619 R_View_WorldVisibility(r_refdef.view.useclipplane);
5620 R_View_UpdateEntityVisible();
5621 R_View_UpdateEntityLighting();
5624 float viewscalefpsadjusted = 1.0f;
5626 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5628 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5629 scale = bound(0.03125f, scale, 1.0f);
5630 *outwidth = (int)ceil(width * scale);
5631 *outheight = (int)ceil(height * scale);
5634 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5636 const float *customclipplane = NULL;
5638 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5639 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5641 // LordHavoc: couldn't figure out how to make this approach the
5642 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5643 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5644 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5645 dist = r_refdef.view.clipplane.dist;
5646 plane[0] = r_refdef.view.clipplane.normal[0];
5647 plane[1] = r_refdef.view.clipplane.normal[1];
5648 plane[2] = r_refdef.view.clipplane.normal[2];
5650 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5653 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5654 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5656 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5657 if (!r_refdef.view.useperspective)
5658 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);
5659 else if (vid.stencil && r_useinfinitefarclip.integer)
5660 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);
5662 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);
5663 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5664 R_SetViewport(&r_refdef.view.viewport);
5665 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5667 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5668 float screenplane[4];
5669 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5670 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5671 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5672 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5673 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5677 void R_EntityMatrix(const matrix4x4_t *matrix)
5679 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5681 gl_modelmatrixchanged = false;
5682 gl_modelmatrix = *matrix;
5683 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5684 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5685 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5686 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5688 switch(vid.renderpath)
5690 case RENDERPATH_D3D9:
5692 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5693 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5696 case RENDERPATH_D3D10:
5697 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5699 case RENDERPATH_D3D11:
5700 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5702 case RENDERPATH_GL11:
5703 case RENDERPATH_GL13:
5704 case RENDERPATH_GLES1:
5706 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5709 case RENDERPATH_SOFT:
5710 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5711 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5713 case RENDERPATH_GL20:
5714 case RENDERPATH_GLES2:
5715 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5716 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5722 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5724 r_viewport_t viewport;
5728 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5729 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);
5730 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5731 R_SetViewport(&viewport);
5732 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5733 GL_Color(1, 1, 1, 1);
5734 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5735 GL_BlendFunc(GL_ONE, GL_ZERO);
5736 GL_ScissorTest(false);
5737 GL_DepthMask(false);
5738 GL_DepthRange(0, 1);
5739 GL_DepthTest(false);
5740 GL_DepthFunc(GL_LEQUAL);
5741 R_EntityMatrix(&identitymatrix);
5742 R_Mesh_ResetTextureState();
5743 GL_PolygonOffset(0, 0);
5744 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5745 switch(vid.renderpath)
5747 case RENDERPATH_GL11:
5748 case RENDERPATH_GL13:
5749 case RENDERPATH_GL20:
5750 case RENDERPATH_GLES1:
5751 case RENDERPATH_GLES2:
5752 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5754 case RENDERPATH_D3D9:
5755 case RENDERPATH_D3D10:
5756 case RENDERPATH_D3D11:
5757 case RENDERPATH_SOFT:
5760 GL_CullFace(GL_NONE);
5765 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5769 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5772 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5776 R_SetupView(true, fbo, depthtexture, colortexture);
5777 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5778 GL_Color(1, 1, 1, 1);
5779 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5780 GL_BlendFunc(GL_ONE, GL_ZERO);
5781 GL_ScissorTest(true);
5783 GL_DepthRange(0, 1);
5785 GL_DepthFunc(GL_LEQUAL);
5786 R_EntityMatrix(&identitymatrix);
5787 R_Mesh_ResetTextureState();
5788 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5789 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5790 switch(vid.renderpath)
5792 case RENDERPATH_GL11:
5793 case RENDERPATH_GL13:
5794 case RENDERPATH_GL20:
5795 case RENDERPATH_GLES1:
5796 case RENDERPATH_GLES2:
5797 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5799 case RENDERPATH_D3D9:
5800 case RENDERPATH_D3D10:
5801 case RENDERPATH_D3D11:
5802 case RENDERPATH_SOFT:
5805 GL_CullFace(r_refdef.view.cullface_back);
5810 R_RenderView_UpdateViewVectors
5813 void R_RenderView_UpdateViewVectors(void)
5815 // break apart the view matrix into vectors for various purposes
5816 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5817 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5818 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5819 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5820 // make an inverted copy of the view matrix for tracking sprites
5821 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5824 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5825 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5827 static void R_Water_StartFrame(void)
5830 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5831 r_waterstate_waterplane_t *p;
5832 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;
5834 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5837 switch(vid.renderpath)
5839 case RENDERPATH_GL20:
5840 case RENDERPATH_D3D9:
5841 case RENDERPATH_D3D10:
5842 case RENDERPATH_D3D11:
5843 case RENDERPATH_SOFT:
5844 case RENDERPATH_GLES2:
5846 case RENDERPATH_GL11:
5847 case RENDERPATH_GL13:
5848 case RENDERPATH_GLES1:
5852 // set waterwidth and waterheight to the water resolution that will be
5853 // used (often less than the screen resolution for faster rendering)
5854 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5856 // calculate desired texture sizes
5857 // can't use water if the card does not support the texture size
5858 if (!r_water.integer || r_showsurfaces.integer)
5859 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5860 else if (vid.support.arb_texture_non_power_of_two)
5862 texturewidth = waterwidth;
5863 textureheight = waterheight;
5864 camerawidth = waterwidth;
5865 cameraheight = waterheight;
5869 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5870 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5871 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5872 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5875 // allocate textures as needed
5876 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))
5878 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5879 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5881 if (p->texture_refraction)
5882 R_FreeTexture(p->texture_refraction);
5883 p->texture_refraction = NULL;
5884 if (p->fbo_refraction)
5885 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5886 p->fbo_refraction = 0;
5887 if (p->texture_reflection)
5888 R_FreeTexture(p->texture_reflection);
5889 p->texture_reflection = NULL;
5890 if (p->fbo_reflection)
5891 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5892 p->fbo_reflection = 0;
5893 if (p->texture_camera)
5894 R_FreeTexture(p->texture_camera);
5895 p->texture_camera = NULL;
5897 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5900 memset(&r_fb.water, 0, sizeof(r_fb.water));
5901 r_fb.water.texturewidth = texturewidth;
5902 r_fb.water.textureheight = textureheight;
5903 r_fb.water.camerawidth = camerawidth;
5904 r_fb.water.cameraheight = cameraheight;
5907 if (r_fb.water.texturewidth)
5909 int scaledwidth, scaledheight;
5911 r_fb.water.enabled = true;
5913 // water resolution is usually reduced
5914 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5915 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5916 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5918 // set up variables that will be used in shader setup
5919 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5920 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5921 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5922 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5925 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5926 r_fb.water.numwaterplanes = 0;
5929 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5931 int planeindex, bestplaneindex, vertexindex;
5932 vec3_t mins, maxs, normal, center, v, n;
5933 vec_t planescore, bestplanescore;
5935 r_waterstate_waterplane_t *p;
5936 texture_t *t = R_GetCurrentTexture(surface->texture);
5938 rsurface.texture = t;
5939 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5940 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5941 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5943 // average the vertex normals, find the surface bounds (after deformvertexes)
5944 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5945 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5946 VectorCopy(n, normal);
5947 VectorCopy(v, mins);
5948 VectorCopy(v, maxs);
5949 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5951 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5952 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5953 VectorAdd(normal, n, normal);
5954 mins[0] = min(mins[0], v[0]);
5955 mins[1] = min(mins[1], v[1]);
5956 mins[2] = min(mins[2], v[2]);
5957 maxs[0] = max(maxs[0], v[0]);
5958 maxs[1] = max(maxs[1], v[1]);
5959 maxs[2] = max(maxs[2], v[2]);
5961 VectorNormalize(normal);
5962 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5964 VectorCopy(normal, plane.normal);
5965 VectorNormalize(plane.normal);
5966 plane.dist = DotProduct(center, plane.normal);
5967 PlaneClassify(&plane);
5968 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5970 // skip backfaces (except if nocullface is set)
5971 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5973 VectorNegate(plane.normal, plane.normal);
5975 PlaneClassify(&plane);
5979 // find a matching plane if there is one
5980 bestplaneindex = -1;
5981 bestplanescore = 1048576.0f;
5982 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5984 if(p->camera_entity == t->camera_entity)
5986 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5987 if (bestplaneindex < 0 || bestplanescore > planescore)
5989 bestplaneindex = planeindex;
5990 bestplanescore = planescore;
5994 planeindex = bestplaneindex;
5995 p = r_fb.water.waterplanes + planeindex;
5997 // if this surface does not fit any known plane rendered this frame, add one
5998 if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6000 // store the new plane
6001 planeindex = r_fb.water.numwaterplanes++;
6002 p = r_fb.water.waterplanes + planeindex;
6004 // clear materialflags and pvs
6005 p->materialflags = 0;
6006 p->pvsvalid = false;
6007 p->camera_entity = t->camera_entity;
6008 VectorCopy(mins, p->mins);
6009 VectorCopy(maxs, p->maxs);
6013 // merge mins/maxs when we're adding this surface to the plane
6014 p->mins[0] = min(p->mins[0], mins[0]);
6015 p->mins[1] = min(p->mins[1], mins[1]);
6016 p->mins[2] = min(p->mins[2], mins[2]);
6017 p->maxs[0] = max(p->maxs[0], maxs[0]);
6018 p->maxs[1] = max(p->maxs[1], maxs[1]);
6019 p->maxs[2] = max(p->maxs[2], maxs[2]);
6021 // merge this surface's materialflags into the waterplane
6022 p->materialflags |= t->currentmaterialflags;
6023 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6025 // merge this surface's PVS into the waterplane
6026 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6027 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6029 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6035 extern cvar_t r_drawparticles;
6036 extern cvar_t r_drawdecals;
6038 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6041 r_refdef_view_t originalview;
6042 r_refdef_view_t myview;
6043 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;
6044 r_waterstate_waterplane_t *p;
6046 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;
6049 originalview = r_refdef.view;
6051 // lowquality hack, temporarily shut down some cvars and restore afterwards
6052 qualityreduction = r_water_lowquality.integer;
6053 if (qualityreduction > 0)
6055 if (qualityreduction >= 1)
6057 old_r_shadows = r_shadows.integer;
6058 old_r_worldrtlight = r_shadow_realtime_world.integer;
6059 old_r_dlight = r_shadow_realtime_dlight.integer;
6060 Cvar_SetValueQuick(&r_shadows, 0);
6061 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6062 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6064 if (qualityreduction >= 2)
6066 old_r_dynamic = r_dynamic.integer;
6067 old_r_particles = r_drawparticles.integer;
6068 old_r_decals = r_drawdecals.integer;
6069 Cvar_SetValueQuick(&r_dynamic, 0);
6070 Cvar_SetValueQuick(&r_drawparticles, 0);
6071 Cvar_SetValueQuick(&r_drawdecals, 0);
6075 // make sure enough textures are allocated
6076 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6078 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6080 if (!p->texture_refraction)
6081 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);
6082 if (!p->texture_refraction)
6086 if (r_fb.water.depthtexture == NULL)
6087 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6088 if (p->fbo_refraction == 0)
6089 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6092 else if (p->materialflags & MATERIALFLAG_CAMERA)
6094 if (!p->texture_camera)
6095 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);
6096 if (!p->texture_camera)
6100 if (r_fb.water.depthtexture == NULL)
6101 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6102 if (p->fbo_camera == 0)
6103 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6107 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6109 if (!p->texture_reflection)
6110 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);
6111 if (!p->texture_reflection)
6115 if (r_fb.water.depthtexture == NULL)
6116 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6117 if (p->fbo_reflection == 0)
6118 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6124 r_refdef.view = originalview;
6125 r_refdef.view.showdebug = false;
6126 r_refdef.view.width = r_fb.water.waterwidth;
6127 r_refdef.view.height = r_fb.water.waterheight;
6128 r_refdef.view.useclipplane = true;
6129 myview = r_refdef.view;
6130 r_fb.water.renderingscene = true;
6131 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6133 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6135 r_refdef.view = myview;
6136 if(r_water_scissormode.integer)
6138 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6139 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6140 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6143 // render reflected scene and copy into texture
6144 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6145 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6146 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6147 r_refdef.view.clipplane = p->plane;
6148 // reverse the cullface settings for this render
6149 r_refdef.view.cullface_front = GL_FRONT;
6150 r_refdef.view.cullface_back = GL_BACK;
6151 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6153 r_refdef.view.usecustompvs = true;
6155 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6157 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6160 r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6161 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6162 R_ClearScreen(r_refdef.fogenabled);
6163 if(r_water_scissormode.integer & 2)
6164 R_View_UpdateWithScissor(myscissor);
6167 R_AnimCache_CacheVisibleEntities();
6168 if(r_water_scissormode.integer & 1)
6169 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6170 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6172 if (!p->fbo_reflection)
6173 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);
6174 r_fb.water.hideplayer = false;
6177 // render the normal view scene and copy into texture
6178 // (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)
6179 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6181 r_refdef.view = myview;
6182 if(r_water_scissormode.integer)
6184 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6185 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6186 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6189 r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6191 r_refdef.view.clipplane = p->plane;
6192 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6193 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6195 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6197 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6198 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6199 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6200 R_RenderView_UpdateViewVectors();
6201 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6203 r_refdef.view.usecustompvs = true;
6204 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);
6208 PlaneClassify(&r_refdef.view.clipplane);
6210 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6211 R_ClearScreen(r_refdef.fogenabled);
6212 if(r_water_scissormode.integer & 2)
6213 R_View_UpdateWithScissor(myscissor);
6216 R_AnimCache_CacheVisibleEntities();
6217 if(r_water_scissormode.integer & 1)
6218 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6219 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6221 if (!p->fbo_refraction)
6222 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);
6223 r_fb.water.hideplayer = false;
6225 else if (p->materialflags & MATERIALFLAG_CAMERA)
6227 r_refdef.view = myview;
6229 r_refdef.view.clipplane = p->plane;
6230 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6231 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6233 r_refdef.view.width = r_fb.water.camerawidth;
6234 r_refdef.view.height = r_fb.water.cameraheight;
6235 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6236 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6237 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6238 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6240 if(p->camera_entity)
6242 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6243 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6246 // note: all of the view is used for displaying... so
6247 // there is no use in scissoring
6249 // reverse the cullface settings for this render
6250 r_refdef.view.cullface_front = GL_FRONT;
6251 r_refdef.view.cullface_back = GL_BACK;
6252 // also reverse the view matrix
6253 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
6254 R_RenderView_UpdateViewVectors();
6255 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6257 r_refdef.view.usecustompvs = true;
6258 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);
6261 // camera needs no clipplane
6262 r_refdef.view.useclipplane = false;
6264 PlaneClassify(&r_refdef.view.clipplane);
6266 r_fb.water.hideplayer = false;
6268 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6269 R_ClearScreen(r_refdef.fogenabled);
6271 R_AnimCache_CacheVisibleEntities();
6272 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6275 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);
6276 r_fb.water.hideplayer = false;
6280 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6281 r_fb.water.renderingscene = false;
6282 r_refdef.view = originalview;
6283 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6284 if (!r_fb.water.depthtexture)
6285 R_ClearScreen(r_refdef.fogenabled);
6287 R_AnimCache_CacheVisibleEntities();
6290 r_refdef.view = originalview;
6291 r_fb.water.renderingscene = false;
6292 Cvar_SetValueQuick(&r_water, 0);
6293 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6295 // lowquality hack, restore cvars
6296 if (qualityreduction > 0)
6298 if (qualityreduction >= 1)
6300 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6301 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6302 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6304 if (qualityreduction >= 2)
6306 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6307 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6308 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6313 static void R_Bloom_StartFrame(void)
6316 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6317 int viewwidth, viewheight;
6318 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6319 textype_t textype = TEXTYPE_COLORBUFFER;
6321 switch (vid.renderpath)
6323 case RENDERPATH_GL20:
6324 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6325 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6327 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6328 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6331 case RENDERPATH_GL11:
6332 case RENDERPATH_GL13:
6333 case RENDERPATH_GLES1:
6334 case RENDERPATH_GLES2:
6335 case RENDERPATH_D3D9:
6336 case RENDERPATH_D3D10:
6337 case RENDERPATH_D3D11:
6338 r_fb.usedepthtextures = false;
6340 case RENDERPATH_SOFT:
6341 r_fb.usedepthtextures = true;
6345 if (r_viewscale_fpsscaling.integer)
6347 double actualframetime;
6348 double targetframetime;
6350 actualframetime = r_refdef.lastdrawscreentime;
6351 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6352 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6353 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6354 if (r_viewscale_fpsscaling_stepsize.value > 0)
6355 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6356 viewscalefpsadjusted += adjust;
6357 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6360 viewscalefpsadjusted = 1.0f;
6362 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6364 switch(vid.renderpath)
6366 case RENDERPATH_GL20:
6367 case RENDERPATH_D3D9:
6368 case RENDERPATH_D3D10:
6369 case RENDERPATH_D3D11:
6370 case RENDERPATH_SOFT:
6371 case RENDERPATH_GLES2:
6373 case RENDERPATH_GL11:
6374 case RENDERPATH_GL13:
6375 case RENDERPATH_GLES1:
6379 // set bloomwidth and bloomheight to the bloom resolution that will be
6380 // used (often less than the screen resolution for faster rendering)
6381 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6382 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6383 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6384 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6385 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6387 // calculate desired texture sizes
6388 if (vid.support.arb_texture_non_power_of_two)
6390 screentexturewidth = vid.width;
6391 screentextureheight = vid.height;
6392 bloomtexturewidth = r_fb.bloomwidth;
6393 bloomtextureheight = r_fb.bloomheight;
6397 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6398 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6399 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6400 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6403 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))
6405 Cvar_SetValueQuick(&r_bloom, 0);
6406 Cvar_SetValueQuick(&r_motionblur, 0);
6407 Cvar_SetValueQuick(&r_damageblur, 0);
6410 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6412 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6414 && r_viewscale.value == 1.0f
6415 && !r_viewscale_fpsscaling.integer)
6416 screentexturewidth = screentextureheight = 0;
6417 if (!r_bloom.integer)
6418 bloomtexturewidth = bloomtextureheight = 0;
6420 // allocate textures as needed
6421 if (r_fb.screentexturewidth != screentexturewidth
6422 || r_fb.screentextureheight != screentextureheight
6423 || r_fb.bloomtexturewidth != bloomtexturewidth
6424 || r_fb.bloomtextureheight != bloomtextureheight
6425 || r_fb.textype != textype
6426 || useviewfbo != (r_fb.fbo != 0))
6428 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6430 if (r_fb.bloomtexture[i])
6431 R_FreeTexture(r_fb.bloomtexture[i]);
6432 r_fb.bloomtexture[i] = NULL;
6434 if (r_fb.bloomfbo[i])
6435 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6436 r_fb.bloomfbo[i] = 0;
6440 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6443 if (r_fb.colortexture)
6444 R_FreeTexture(r_fb.colortexture);
6445 r_fb.colortexture = NULL;
6447 if (r_fb.depthtexture)
6448 R_FreeTexture(r_fb.depthtexture);
6449 r_fb.depthtexture = NULL;
6451 if (r_fb.ghosttexture)
6452 R_FreeTexture(r_fb.ghosttexture);
6453 r_fb.ghosttexture = NULL;
6455 r_fb.screentexturewidth = screentexturewidth;
6456 r_fb.screentextureheight = screentextureheight;
6457 r_fb.bloomtexturewidth = bloomtexturewidth;
6458 r_fb.bloomtextureheight = bloomtextureheight;
6459 r_fb.textype = textype;
6461 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6463 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6464 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);
6465 r_fb.ghosttexture_valid = false;
6466 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);
6469 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6470 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6471 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6475 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6477 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6479 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);
6481 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6486 // bloom texture is a different resolution
6487 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6488 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6489 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6490 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6491 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6493 // set up a texcoord array for the full resolution screen image
6494 // (we have to keep this around to copy back during final render)
6495 r_fb.screentexcoord2f[0] = 0;
6496 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6497 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6498 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6499 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6500 r_fb.screentexcoord2f[5] = 0;
6501 r_fb.screentexcoord2f[6] = 0;
6502 r_fb.screentexcoord2f[7] = 0;
6506 for (i = 1;i < 8;i += 2)
6508 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6512 // set up a texcoord array for the reduced resolution bloom image
6513 // (which will be additive blended over the screen image)
6514 r_fb.bloomtexcoord2f[0] = 0;
6515 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6516 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6517 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6518 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6519 r_fb.bloomtexcoord2f[5] = 0;
6520 r_fb.bloomtexcoord2f[6] = 0;
6521 r_fb.bloomtexcoord2f[7] = 0;
6523 switch(vid.renderpath)
6525 case RENDERPATH_GL11:
6526 case RENDERPATH_GL13:
6527 case RENDERPATH_GL20:
6528 case RENDERPATH_SOFT:
6529 case RENDERPATH_GLES1:
6530 case RENDERPATH_GLES2:
6532 case RENDERPATH_D3D9:
6533 case RENDERPATH_D3D10:
6534 case RENDERPATH_D3D11:
6535 for (i = 0;i < 4;i++)
6537 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6538 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6539 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6540 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6545 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6548 r_refdef.view.clear = true;
6551 static void R_Bloom_MakeTexture(void)
6554 float xoffset, yoffset, r, brighten;
6556 float colorscale = r_bloom_colorscale.value;
6558 r_refdef.stats[r_stat_bloom]++;
6561 // this copy is unnecessary since it happens in R_BlendView already
6564 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);
6565 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6569 // scale down screen texture to the bloom texture size
6571 r_fb.bloomindex = 0;
6572 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6573 R_SetViewport(&r_fb.bloomviewport);
6574 GL_DepthTest(false);
6575 GL_BlendFunc(GL_ONE, GL_ZERO);
6576 GL_Color(colorscale, colorscale, colorscale, 1);
6577 // 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...
6578 switch(vid.renderpath)
6580 case RENDERPATH_GL11:
6581 case RENDERPATH_GL13:
6582 case RENDERPATH_GL20:
6583 case RENDERPATH_GLES1:
6584 case RENDERPATH_GLES2:
6585 case RENDERPATH_SOFT:
6586 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6588 case RENDERPATH_D3D9:
6589 case RENDERPATH_D3D10:
6590 case RENDERPATH_D3D11:
6591 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6594 // TODO: do boxfilter scale-down in shader?
6595 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6596 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6597 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6599 // we now have a properly scaled bloom image
6600 if (!r_fb.bloomfbo[r_fb.bloomindex])
6602 // copy it into the bloom texture
6603 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);
6604 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6607 // multiply bloom image by itself as many times as desired
6608 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6610 intex = r_fb.bloomtexture[r_fb.bloomindex];
6611 r_fb.bloomindex ^= 1;
6612 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6614 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6615 if (!r_fb.bloomfbo[r_fb.bloomindex])
6617 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6618 GL_Color(r,r,r,1); // apply fix factor
6623 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6624 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6625 GL_Color(1,1,1,1); // no fix factor supported here
6627 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6628 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6629 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6630 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6632 if (!r_fb.bloomfbo[r_fb.bloomindex])
6634 // copy the darkened image to a texture
6635 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);
6636 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6640 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6641 brighten = r_bloom_brighten.value;
6642 brighten = sqrt(brighten);
6644 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6646 for (dir = 0;dir < 2;dir++)
6648 intex = r_fb.bloomtexture[r_fb.bloomindex];
6649 r_fb.bloomindex ^= 1;
6650 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6651 // blend on at multiple vertical offsets to achieve a vertical blur
6652 // TODO: do offset blends using GLSL
6653 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6654 GL_BlendFunc(GL_ONE, GL_ZERO);
6655 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6656 for (x = -range;x <= range;x++)
6658 if (!dir){xoffset = 0;yoffset = x;}
6659 else {xoffset = x;yoffset = 0;}
6660 xoffset /= (float)r_fb.bloomtexturewidth;
6661 yoffset /= (float)r_fb.bloomtextureheight;
6662 // compute a texcoord array with the specified x and y offset
6663 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6664 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6665 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6666 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6667 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6668 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6669 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6670 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6671 // this r value looks like a 'dot' particle, fading sharply to
6672 // black at the edges
6673 // (probably not realistic but looks good enough)
6674 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6675 //r = brighten/(range*2+1);
6676 r = brighten / (range * 2 + 1);
6678 r *= (1 - x*x/(float)(range*range));
6679 GL_Color(r, r, r, 1);
6680 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6681 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6682 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6683 GL_BlendFunc(GL_ONE, GL_ONE);
6686 if (!r_fb.bloomfbo[r_fb.bloomindex])
6688 // copy the vertically or horizontally blurred bloom view to a texture
6689 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);
6690 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6695 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6697 unsigned int permutation;
6698 float uservecs[4][4];
6700 R_EntityMatrix(&identitymatrix);
6702 switch (vid.renderpath)
6704 case RENDERPATH_GL20:
6705 case RENDERPATH_D3D9:
6706 case RENDERPATH_D3D10:
6707 case RENDERPATH_D3D11:
6708 case RENDERPATH_SOFT:
6709 case RENDERPATH_GLES2:
6711 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6712 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6713 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6714 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6715 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6717 if (r_fb.colortexture)
6721 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);
6722 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6725 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6727 // declare variables
6728 float blur_factor, blur_mouseaccel, blur_velocity;
6729 static float blur_average;
6730 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6732 // set a goal for the factoring
6733 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6734 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6735 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6736 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6737 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6738 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6740 // from the goal, pick an averaged value between goal and last value
6741 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6742 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6744 // enforce minimum amount of blur
6745 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6747 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6749 // calculate values into a standard alpha
6750 cl.motionbluralpha = 1 - exp(-
6752 (r_motionblur.value * blur_factor / 80)
6754 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6757 max(0.0001, cl.time - cl.oldtime) // fps independent
6760 // randomization for the blur value to combat persistent ghosting
6761 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6762 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6765 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6766 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6768 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6769 GL_Color(1, 1, 1, cl.motionbluralpha);
6770 switch(vid.renderpath)
6772 case RENDERPATH_GL11:
6773 case RENDERPATH_GL13:
6774 case RENDERPATH_GL20:
6775 case RENDERPATH_GLES1:
6776 case RENDERPATH_GLES2:
6777 case RENDERPATH_SOFT:
6778 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6780 case RENDERPATH_D3D9:
6781 case RENDERPATH_D3D10:
6782 case RENDERPATH_D3D11:
6783 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6786 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6787 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6788 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6791 // updates old view angles for next pass
6792 VectorCopy(cl.viewangles, blur_oldangles);
6794 // copy view into the ghost texture
6795 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);
6796 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6797 r_fb.ghosttexture_valid = true;
6802 // no r_fb.colortexture means we're rendering to the real fb
6803 // we may still have to do view tint...
6804 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6806 // apply a color tint to the whole view
6807 R_ResetViewRendering2D(0, NULL, NULL);
6808 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6809 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6810 R_SetupShader_Generic_NoTexture(false, true);
6811 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6812 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6814 break; // no screen processing, no bloom, skip it
6817 if (r_fb.bloomtexture[0])
6819 // make the bloom texture
6820 R_Bloom_MakeTexture();
6823 #if _MSC_VER >= 1400
6824 #define sscanf sscanf_s
6826 memset(uservecs, 0, sizeof(uservecs));
6827 if (r_glsl_postprocess_uservec1_enable.integer)
6828 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6829 if (r_glsl_postprocess_uservec2_enable.integer)
6830 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6831 if (r_glsl_postprocess_uservec3_enable.integer)
6832 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6833 if (r_glsl_postprocess_uservec4_enable.integer)
6834 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6836 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6837 GL_Color(1, 1, 1, 1);
6838 GL_BlendFunc(GL_ONE, GL_ZERO);
6840 switch(vid.renderpath)
6842 case RENDERPATH_GL20:
6843 case RENDERPATH_GLES2:
6844 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6845 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6846 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6847 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6848 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6849 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]);
6850 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6851 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]);
6852 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]);
6853 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]);
6854 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]);
6855 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6856 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6857 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);
6859 case RENDERPATH_D3D9:
6861 // 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...
6862 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6863 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6864 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6865 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6866 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6867 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6868 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6869 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6870 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6871 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6872 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6873 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6874 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6875 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6878 case RENDERPATH_D3D10:
6879 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6881 case RENDERPATH_D3D11:
6882 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6884 case RENDERPATH_SOFT:
6885 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6886 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6887 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6888 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6889 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6890 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6891 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6892 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6893 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6894 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6895 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6896 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6897 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6898 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6903 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6904 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6906 case RENDERPATH_GL11:
6907 case RENDERPATH_GL13:
6908 case RENDERPATH_GLES1:
6909 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6911 // apply a color tint to the whole view
6912 R_ResetViewRendering2D(0, NULL, NULL);
6913 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6914 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6915 R_SetupShader_Generic_NoTexture(false, true);
6916 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6917 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6923 matrix4x4_t r_waterscrollmatrix;
6925 void R_UpdateFog(void)
6928 if (gamemode == GAME_NEHAHRA)
6930 if (gl_fogenable.integer)
6932 r_refdef.oldgl_fogenable = true;
6933 r_refdef.fog_density = gl_fogdensity.value;
6934 r_refdef.fog_red = gl_fogred.value;
6935 r_refdef.fog_green = gl_foggreen.value;
6936 r_refdef.fog_blue = gl_fogblue.value;
6937 r_refdef.fog_alpha = 1;
6938 r_refdef.fog_start = 0;
6939 r_refdef.fog_end = gl_skyclip.value;
6940 r_refdef.fog_height = 1<<30;
6941 r_refdef.fog_fadedepth = 128;
6943 else if (r_refdef.oldgl_fogenable)
6945 r_refdef.oldgl_fogenable = false;
6946 r_refdef.fog_density = 0;
6947 r_refdef.fog_red = 0;
6948 r_refdef.fog_green = 0;
6949 r_refdef.fog_blue = 0;
6950 r_refdef.fog_alpha = 0;
6951 r_refdef.fog_start = 0;
6952 r_refdef.fog_end = 0;
6953 r_refdef.fog_height = 1<<30;
6954 r_refdef.fog_fadedepth = 128;
6959 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6960 r_refdef.fog_start = max(0, r_refdef.fog_start);
6961 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6963 if (r_refdef.fog_density && r_drawfog.integer)
6965 r_refdef.fogenabled = true;
6966 // this is the point where the fog reaches 0.9986 alpha, which we
6967 // consider a good enough cutoff point for the texture
6968 // (0.9986 * 256 == 255.6)
6969 if (r_fog_exp2.integer)
6970 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6972 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6973 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6974 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6975 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6976 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6977 R_BuildFogHeightTexture();
6978 // fog color was already set
6979 // update the fog texture
6980 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)
6981 R_BuildFogTexture();
6982 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6983 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6986 r_refdef.fogenabled = false;
6989 if (r_refdef.fog_density)
6991 r_refdef.fogcolor[0] = r_refdef.fog_red;
6992 r_refdef.fogcolor[1] = r_refdef.fog_green;
6993 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6995 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6996 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6997 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6998 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7002 VectorCopy(r_refdef.fogcolor, fogvec);
7003 // color.rgb *= ContrastBoost * SceneBrightness;
7004 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7005 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7006 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7007 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7012 void R_UpdateVariables(void)
7016 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7018 r_refdef.farclip = r_farclip_base.value;
7019 if (r_refdef.scene.worldmodel)
7020 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7021 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7023 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7024 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7025 r_refdef.polygonfactor = 0;
7026 r_refdef.polygonoffset = 0;
7027 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7028 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7030 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7031 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7032 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7033 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7034 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7035 if (FAKELIGHT_ENABLED)
7037 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7039 else if (r_refdef.scene.worldmodel)
7041 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7043 if (r_showsurfaces.integer)
7045 r_refdef.scene.rtworld = false;
7046 r_refdef.scene.rtworldshadows = false;
7047 r_refdef.scene.rtdlight = false;
7048 r_refdef.scene.rtdlightshadows = false;
7049 r_refdef.lightmapintensity = 0;
7052 r_gpuskeletal = false;
7053 switch(vid.renderpath)
7055 case RENDERPATH_GL20:
7056 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7057 case RENDERPATH_D3D9:
7058 case RENDERPATH_D3D10:
7059 case RENDERPATH_D3D11:
7060 case RENDERPATH_SOFT:
7061 case RENDERPATH_GLES2:
7062 if(v_glslgamma.integer && !vid_gammatables_trivial)
7064 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7066 // build GLSL gamma texture
7067 #define RAMPWIDTH 256
7068 unsigned short ramp[RAMPWIDTH * 3];
7069 unsigned char rampbgr[RAMPWIDTH][4];
7072 r_texture_gammaramps_serial = vid_gammatables_serial;
7074 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7075 for(i = 0; i < RAMPWIDTH; ++i)
7077 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7078 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7079 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7082 if (r_texture_gammaramps)
7084 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7088 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7094 // remove GLSL gamma texture
7097 case RENDERPATH_GL11:
7098 case RENDERPATH_GL13:
7099 case RENDERPATH_GLES1:
7104 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7105 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7111 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7112 if( scenetype != r_currentscenetype ) {
7113 // store the old scenetype
7114 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7115 r_currentscenetype = scenetype;
7116 // move in the new scene
7117 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7126 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7128 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7129 if( scenetype == r_currentscenetype ) {
7130 return &r_refdef.scene;
7132 return &r_scenes_store[ scenetype ];
7136 static int R_SortEntities_Compare(const void *ap, const void *bp)
7138 const entity_render_t *a = *(const entity_render_t **)ap;
7139 const entity_render_t *b = *(const entity_render_t **)bp;
7142 if(a->model < b->model)
7144 if(a->model > b->model)
7148 // TODO possibly calculate the REAL skinnum here first using
7150 if(a->skinnum < b->skinnum)
7152 if(a->skinnum > b->skinnum)
7155 // everything we compared is equal
7158 static void R_SortEntities(void)
7160 // below or equal 2 ents, sorting never gains anything
7161 if(r_refdef.scene.numentities <= 2)
7164 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7172 int dpsoftrast_test;
7173 extern cvar_t r_shadow_bouncegrid;
7174 void R_RenderView(void)
7176 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7178 rtexture_t *depthtexture;
7179 rtexture_t *colortexture;
7181 dpsoftrast_test = r_test.integer;
7183 if (r_timereport_active)
7184 R_TimeReport("start");
7185 r_textureframe++; // used only by R_GetCurrentTexture
7186 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7188 if(R_CompileShader_CheckStaticParms())
7191 if (!r_drawentities.integer)
7192 r_refdef.scene.numentities = 0;
7193 else if (r_sortentities.integer)
7196 R_AnimCache_ClearCache();
7198 /* adjust for stereo display */
7199 if(R_Stereo_Active())
7201 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);
7202 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7205 if (r_refdef.view.isoverlay)
7207 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7208 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7209 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7210 R_TimeReport("depthclear");
7212 r_refdef.view.showdebug = false;
7214 r_fb.water.enabled = false;
7215 r_fb.water.numwaterplanes = 0;
7217 R_RenderScene(0, NULL, NULL);
7219 r_refdef.view.matrix = originalmatrix;
7225 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7227 r_refdef.view.matrix = originalmatrix;
7231 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7233 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7234 // in sRGB fallback, behave similar to true sRGB: convert this
7235 // value from linear to sRGB
7236 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7238 R_RenderView_UpdateViewVectors();
7240 R_Shadow_UpdateWorldLightSelection();
7242 R_Bloom_StartFrame();
7244 // apply bloom brightness offset
7245 if(r_fb.bloomtexture[0])
7246 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7248 R_Water_StartFrame();
7250 // now we probably have an fbo to render into
7252 depthtexture = r_fb.depthtexture;
7253 colortexture = r_fb.colortexture;
7256 if (r_timereport_active)
7257 R_TimeReport("viewsetup");
7259 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7261 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7263 R_ClearScreen(r_refdef.fogenabled);
7264 if (r_timereport_active)
7265 R_TimeReport("viewclear");
7267 r_refdef.view.clear = true;
7269 r_refdef.view.showdebug = true;
7272 if (r_timereport_active)
7273 R_TimeReport("visibility");
7275 R_AnimCache_CacheVisibleEntities();
7276 if (r_timereport_active)
7277 R_TimeReport("animcache");
7279 R_Shadow_UpdateBounceGridTexture();
7280 if (r_timereport_active && r_shadow_bouncegrid.integer)
7281 R_TimeReport("bouncegrid");
7283 r_fb.water.numwaterplanes = 0;
7284 if (r_fb.water.enabled)
7285 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7287 R_RenderScene(fbo, depthtexture, colortexture);
7288 r_fb.water.numwaterplanes = 0;
7290 R_BlendView(fbo, depthtexture, colortexture);
7291 if (r_timereport_active)
7292 R_TimeReport("blendview");
7294 GL_Scissor(0, 0, vid.width, vid.height);
7295 GL_ScissorTest(false);
7297 r_refdef.view.matrix = originalmatrix;
7302 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7304 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7306 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7307 if (r_timereport_active)
7308 R_TimeReport("waterworld");
7311 // don't let sound skip if going slow
7312 if (r_refdef.scene.extraupdate)
7315 R_DrawModelsAddWaterPlanes();
7316 if (r_timereport_active)
7317 R_TimeReport("watermodels");
7319 if (r_fb.water.numwaterplanes)
7321 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7322 if (r_timereport_active)
7323 R_TimeReport("waterscenes");
7327 extern cvar_t cl_locs_show;
7328 static void R_DrawLocs(void);
7329 static void R_DrawEntityBBoxes(void);
7330 static void R_DrawModelDecals(void);
7331 extern cvar_t cl_decals_newsystem;
7332 extern qboolean r_shadow_usingdeferredprepass;
7333 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7335 qboolean shadowmapping = false;
7337 if (r_timereport_active)
7338 R_TimeReport("beginscene");
7340 r_refdef.stats[r_stat_renders]++;
7344 // don't let sound skip if going slow
7345 if (r_refdef.scene.extraupdate)
7348 R_MeshQueue_BeginScene();
7352 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);
7354 if (r_timereport_active)
7355 R_TimeReport("skystartframe");
7357 if (cl.csqc_vidvars.drawworld)
7359 // don't let sound skip if going slow
7360 if (r_refdef.scene.extraupdate)
7363 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7365 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7366 if (r_timereport_active)
7367 R_TimeReport("worldsky");
7370 if (R_DrawBrushModelsSky() && r_timereport_active)
7371 R_TimeReport("bmodelsky");
7373 if (skyrendermasked && skyrenderlater)
7375 // we have to force off the water clipping plane while rendering sky
7376 R_SetupView(false, fbo, depthtexture, colortexture);
7378 R_SetupView(true, fbo, depthtexture, colortexture);
7379 if (r_timereport_active)
7380 R_TimeReport("sky");
7384 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7385 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7386 R_Shadow_PrepareModelShadows();
7387 if (r_timereport_active)
7388 R_TimeReport("preparelights");
7390 if (R_Shadow_ShadowMappingEnabled())
7391 shadowmapping = true;
7393 if (r_shadow_usingdeferredprepass)
7394 R_Shadow_DrawPrepass();
7396 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7398 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7399 if (r_timereport_active)
7400 R_TimeReport("worlddepth");
7402 if (r_depthfirst.integer >= 2)
7404 R_DrawModelsDepth();
7405 if (r_timereport_active)
7406 R_TimeReport("modeldepth");
7409 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7411 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7412 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7413 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7414 // don't let sound skip if going slow
7415 if (r_refdef.scene.extraupdate)
7419 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7421 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7422 if (r_timereport_active)
7423 R_TimeReport("world");
7426 // don't let sound skip if going slow
7427 if (r_refdef.scene.extraupdate)
7431 if (r_timereport_active)
7432 R_TimeReport("models");
7434 // don't let sound skip if going slow
7435 if (r_refdef.scene.extraupdate)
7438 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7440 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7441 R_DrawModelShadows(fbo, depthtexture, colortexture);
7442 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7443 // don't let sound skip if going slow
7444 if (r_refdef.scene.extraupdate)
7448 if (!r_shadow_usingdeferredprepass)
7450 R_Shadow_DrawLights();
7451 if (r_timereport_active)
7452 R_TimeReport("rtlights");
7455 // don't let sound skip if going slow
7456 if (r_refdef.scene.extraupdate)
7459 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7461 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7462 R_DrawModelShadows(fbo, depthtexture, colortexture);
7463 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7464 // don't let sound skip if going slow
7465 if (r_refdef.scene.extraupdate)
7469 if (cl.csqc_vidvars.drawworld)
7471 if (cl_decals_newsystem.integer)
7473 R_DrawModelDecals();
7474 if (r_timereport_active)
7475 R_TimeReport("modeldecals");
7480 if (r_timereport_active)
7481 R_TimeReport("decals");
7485 if (r_timereport_active)
7486 R_TimeReport("particles");
7489 if (r_timereport_active)
7490 R_TimeReport("explosions");
7492 R_DrawLightningBeams();
7493 if (r_timereport_active)
7494 R_TimeReport("lightning");
7498 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7500 if (r_refdef.view.showdebug)
7502 if (cl_locs_show.integer)
7505 if (r_timereport_active)
7506 R_TimeReport("showlocs");
7509 if (r_drawportals.integer)
7512 if (r_timereport_active)
7513 R_TimeReport("portals");
7516 if (r_showbboxes.value > 0)
7518 R_DrawEntityBBoxes();
7519 if (r_timereport_active)
7520 R_TimeReport("bboxes");
7524 if (r_transparent.integer)
7526 R_MeshQueue_RenderTransparent();
7527 if (r_timereport_active)
7528 R_TimeReport("drawtrans");
7531 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))
7533 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7534 if (r_timereport_active)
7535 R_TimeReport("worlddebug");
7536 R_DrawModelsDebug();
7537 if (r_timereport_active)
7538 R_TimeReport("modeldebug");
7541 if (cl.csqc_vidvars.drawworld)
7543 R_Shadow_DrawCoronas();
7544 if (r_timereport_active)
7545 R_TimeReport("coronas");
7550 GL_DepthTest(false);
7551 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7552 GL_Color(1, 1, 1, 1);
7553 qglBegin(GL_POLYGON);
7554 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7555 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7556 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7557 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7559 qglBegin(GL_POLYGON);
7560 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]);
7561 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]);
7562 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]);
7563 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]);
7565 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7569 // don't let sound skip if going slow
7570 if (r_refdef.scene.extraupdate)
7574 static const unsigned short bboxelements[36] =
7584 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7587 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7589 RSurf_ActiveWorldEntity();
7591 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7592 GL_DepthMask(false);
7593 GL_DepthRange(0, 1);
7594 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7595 // R_Mesh_ResetTextureState();
7597 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7598 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7599 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7600 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7601 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7602 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7603 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7604 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7605 R_FillColors(color4f, 8, cr, cg, cb, ca);
7606 if (r_refdef.fogenabled)
7608 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7610 f1 = RSurf_FogVertex(v);
7612 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7613 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7614 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7617 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7618 R_Mesh_ResetTextureState();
7619 R_SetupShader_Generic_NoTexture(false, false);
7620 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7623 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7625 prvm_prog_t *prog = SVVM_prog;
7628 prvm_edict_t *edict;
7630 // this function draws bounding boxes of server entities
7634 GL_CullFace(GL_NONE);
7635 R_SetupShader_Generic_NoTexture(false, false);
7637 for (i = 0;i < numsurfaces;i++)
7639 edict = PRVM_EDICT_NUM(surfacelist[i]);
7640 switch ((int)PRVM_serveredictfloat(edict, solid))
7642 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7643 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7644 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7645 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7646 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7647 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7648 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7650 color[3] *= r_showbboxes.value;
7651 color[3] = bound(0, color[3], 1);
7652 GL_DepthTest(!r_showdisabledepthtest.integer);
7653 GL_CullFace(r_refdef.view.cullface_front);
7654 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7658 static void R_DrawEntityBBoxes(void)
7661 prvm_edict_t *edict;
7663 prvm_prog_t *prog = SVVM_prog;
7665 // this function draws bounding boxes of server entities
7669 for (i = 0;i < prog->num_edicts;i++)
7671 edict = PRVM_EDICT_NUM(i);
7672 if (edict->priv.server->free)
7674 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7675 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7677 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7679 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7680 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7684 static const int nomodelelement3i[24] =
7696 static const unsigned short nomodelelement3s[24] =
7708 static const float nomodelvertex3f[6*3] =
7718 static const float nomodelcolor4f[6*4] =
7720 0.0f, 0.0f, 0.5f, 1.0f,
7721 0.0f, 0.0f, 0.5f, 1.0f,
7722 0.0f, 0.5f, 0.0f, 1.0f,
7723 0.0f, 0.5f, 0.0f, 1.0f,
7724 0.5f, 0.0f, 0.0f, 1.0f,
7725 0.5f, 0.0f, 0.0f, 1.0f
7728 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7734 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);
7736 // this is only called once per entity so numsurfaces is always 1, and
7737 // surfacelist is always {0}, so this code does not handle batches
7739 if (rsurface.ent_flags & RENDER_ADDITIVE)
7741 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7742 GL_DepthMask(false);
7744 else if (rsurface.colormod[3] < 1)
7746 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7747 GL_DepthMask(false);
7751 GL_BlendFunc(GL_ONE, GL_ZERO);
7754 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7755 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7756 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7757 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7758 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7759 for (i = 0, c = color4f;i < 6;i++, c += 4)
7761 c[0] *= rsurface.colormod[0];
7762 c[1] *= rsurface.colormod[1];
7763 c[2] *= rsurface.colormod[2];
7764 c[3] *= rsurface.colormod[3];
7766 if (r_refdef.fogenabled)
7768 for (i = 0, c = color4f;i < 6;i++, c += 4)
7770 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7772 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7773 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7774 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7777 // R_Mesh_ResetTextureState();
7778 R_SetupShader_Generic_NoTexture(false, false);
7779 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7780 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7783 void R_DrawNoModel(entity_render_t *ent)
7786 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7787 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7788 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7790 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7793 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7795 vec3_t right1, right2, diff, normal;
7797 VectorSubtract (org2, org1, normal);
7799 // calculate 'right' vector for start
7800 VectorSubtract (r_refdef.view.origin, org1, diff);
7801 CrossProduct (normal, diff, right1);
7802 VectorNormalize (right1);
7804 // calculate 'right' vector for end
7805 VectorSubtract (r_refdef.view.origin, org2, diff);
7806 CrossProduct (normal, diff, right2);
7807 VectorNormalize (right2);
7809 vert[ 0] = org1[0] + width * right1[0];
7810 vert[ 1] = org1[1] + width * right1[1];
7811 vert[ 2] = org1[2] + width * right1[2];
7812 vert[ 3] = org1[0] - width * right1[0];
7813 vert[ 4] = org1[1] - width * right1[1];
7814 vert[ 5] = org1[2] - width * right1[2];
7815 vert[ 6] = org2[0] - width * right2[0];
7816 vert[ 7] = org2[1] - width * right2[1];
7817 vert[ 8] = org2[2] - width * right2[2];
7818 vert[ 9] = org2[0] + width * right2[0];
7819 vert[10] = org2[1] + width * right2[1];
7820 vert[11] = org2[2] + width * right2[2];
7823 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)
7825 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7826 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7827 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7828 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7829 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7830 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7831 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7832 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7833 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7834 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7835 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7836 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7839 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7844 VectorSet(v, x, y, z);
7845 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7846 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7848 if (i == mesh->numvertices)
7850 if (mesh->numvertices < mesh->maxvertices)
7852 VectorCopy(v, vertex3f);
7853 mesh->numvertices++;
7855 return mesh->numvertices;
7861 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7865 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7866 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7867 e = mesh->element3i + mesh->numtriangles * 3;
7868 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7870 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7871 if (mesh->numtriangles < mesh->maxtriangles)
7876 mesh->numtriangles++;
7878 element[1] = element[2];
7882 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7886 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7887 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7888 e = mesh->element3i + mesh->numtriangles * 3;
7889 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7891 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7892 if (mesh->numtriangles < mesh->maxtriangles)
7897 mesh->numtriangles++;
7899 element[1] = element[2];
7903 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7904 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7906 int planenum, planenum2;
7909 mplane_t *plane, *plane2;
7911 double temppoints[2][256*3];
7912 // figure out how large a bounding box we need to properly compute this brush
7914 for (w = 0;w < numplanes;w++)
7915 maxdist = max(maxdist, fabs(planes[w].dist));
7916 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7917 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7918 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7922 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7923 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7925 if (planenum2 == planenum)
7927 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);
7930 if (tempnumpoints < 3)
7932 // generate elements forming a triangle fan for this polygon
7933 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7937 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)
7939 texturelayer_t *layer;
7940 layer = t->currentlayers + t->currentnumlayers++;
7942 layer->depthmask = depthmask;
7943 layer->blendfunc1 = blendfunc1;
7944 layer->blendfunc2 = blendfunc2;
7945 layer->texture = texture;
7946 layer->texmatrix = *matrix;
7947 layer->color[0] = r;
7948 layer->color[1] = g;
7949 layer->color[2] = b;
7950 layer->color[3] = a;
7953 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7955 if(parms[0] == 0 && parms[1] == 0)
7957 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7958 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7963 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7966 index = parms[2] + rsurface.shadertime * parms[3];
7967 index -= floor(index);
7968 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7971 case Q3WAVEFUNC_NONE:
7972 case Q3WAVEFUNC_NOISE:
7973 case Q3WAVEFUNC_COUNT:
7976 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7977 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7978 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7979 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7980 case Q3WAVEFUNC_TRIANGLE:
7982 f = index - floor(index);
7995 f = parms[0] + parms[1] * f;
7996 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7997 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8001 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8007 matrix4x4_t matrix, temp;
8008 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8009 // it's better to have one huge fixup every 9 hours than gradual
8010 // degradation over time which looks consistently bad after many hours.
8012 // tcmod scroll in particular suffers from this degradation which can't be
8013 // effectively worked around even with floor() tricks because we don't
8014 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8015 // a workaround involving floor() would be incorrect anyway...
8016 shadertime = rsurface.shadertime;
8017 if (shadertime >= 32768.0f)
8018 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8019 switch(tcmod->tcmod)
8023 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8024 matrix = r_waterscrollmatrix;
8026 matrix = identitymatrix;
8028 case Q3TCMOD_ENTITYTRANSLATE:
8029 // this is used in Q3 to allow the gamecode to control texcoord
8030 // scrolling on the entity, which is not supported in darkplaces yet.
8031 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8033 case Q3TCMOD_ROTATE:
8034 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8035 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8036 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8039 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8041 case Q3TCMOD_SCROLL:
8042 // this particular tcmod is the most prone to precision breakdown
8043 // at large values, but as we wrap shadertime it won't be obvious
8045 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * rsurface.shadertime, tcmod->parms[1] * rsurface.shadertime, 0);
8047 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8048 w = (int) tcmod->parms[0];
8049 h = (int) tcmod->parms[1];
8050 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8052 idx = (int) floor(f * w * h);
8053 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8055 case Q3TCMOD_STRETCH:
8056 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8057 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8059 case Q3TCMOD_TRANSFORM:
8060 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8061 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8062 VectorSet(tcmat + 6, 0 , 0 , 1);
8063 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8064 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8066 case Q3TCMOD_TURBULENT:
8067 // this is handled in the RSurf_PrepareVertices function
8068 matrix = identitymatrix;
8072 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8075 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8077 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8078 char name[MAX_QPATH];
8079 skinframe_t *skinframe;
8080 unsigned char pixels[296*194];
8081 strlcpy(cache->name, skinname, sizeof(cache->name));
8082 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8083 if (developer_loading.integer)
8084 Con_Printf("loading %s\n", name);
8085 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8086 if (!skinframe || !skinframe->base)
8089 fs_offset_t filesize;
8091 f = FS_LoadFile(name, tempmempool, true, &filesize);
8094 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8095 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8099 cache->skinframe = skinframe;
8102 texture_t *R_GetCurrentTexture(texture_t *t)
8105 const entity_render_t *ent = rsurface.entity;
8106 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8107 q3shaderinfo_layer_tcmod_t *tcmod;
8109 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8110 return t->currentframe;
8111 t->update_lastrenderframe = r_textureframe;
8112 t->update_lastrenderentity = (void *)ent;
8114 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8115 t->camera_entity = ent->entitynumber;
8117 t->camera_entity = 0;
8119 // switch to an alternate material if this is a q1bsp animated material
8121 texture_t *texture = t;
8122 int s = rsurface.ent_skinnum;
8123 if ((unsigned int)s >= (unsigned int)model->numskins)
8125 if (model->skinscenes)
8127 if (model->skinscenes[s].framecount > 1)
8128 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8130 s = model->skinscenes[s].firstframe;
8133 t = t + s * model->num_surfaces;
8136 // use an alternate animation if the entity's frame is not 0,
8137 // and only if the texture has an alternate animation
8138 if (rsurface.ent_alttextures && t->anim_total[1])
8139 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8141 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8143 texture->currentframe = t;
8146 // update currentskinframe to be a qw skin or animation frame
8147 if (rsurface.ent_qwskin >= 0)
8149 i = rsurface.ent_qwskin;
8150 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8152 r_qwskincache_size = cl.maxclients;
8154 Mem_Free(r_qwskincache);
8155 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8157 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8158 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8159 t->currentskinframe = r_qwskincache[i].skinframe;
8160 if (t->currentskinframe == NULL)
8161 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8163 else if (t->numskinframes >= 2)
8164 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8165 if (t->backgroundnumskinframes >= 2)
8166 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8168 t->currentmaterialflags = t->basematerialflags;
8169 t->currentalpha = rsurface.colormod[3];
8170 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8171 t->currentalpha *= r_wateralpha.value;
8172 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8173 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8174 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8175 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8176 if (!(rsurface.ent_flags & RENDER_LIGHT))
8177 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8178 else if (FAKELIGHT_ENABLED)
8180 // no modellight if using fakelight for the map
8182 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8184 // pick a model lighting mode
8185 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8186 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8188 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8190 if (rsurface.ent_flags & RENDER_ADDITIVE)
8191 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8192 else if (t->currentalpha < 1)
8193 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8194 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8195 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8196 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8197 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8198 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8199 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8200 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8201 if (t->backgroundnumskinframes)
8202 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8203 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8205 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8206 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8209 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8210 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8212 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8213 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8215 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8216 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8218 // there is no tcmod
8219 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8221 t->currenttexmatrix = r_waterscrollmatrix;
8222 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8224 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8226 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8227 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8230 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8231 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8232 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8233 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8235 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8236 if (t->currentskinframe->qpixels)
8237 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8238 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8239 if (!t->basetexture)
8240 t->basetexture = r_texture_notexture;
8241 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8242 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8243 t->nmaptexture = t->currentskinframe->nmap;
8244 if (!t->nmaptexture)
8245 t->nmaptexture = r_texture_blanknormalmap;
8246 t->glosstexture = r_texture_black;
8247 t->glowtexture = t->currentskinframe->glow;
8248 t->fogtexture = t->currentskinframe->fog;
8249 t->reflectmasktexture = t->currentskinframe->reflect;
8250 if (t->backgroundnumskinframes)
8252 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8253 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8254 t->backgroundglosstexture = r_texture_black;
8255 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8256 if (!t->backgroundnmaptexture)
8257 t->backgroundnmaptexture = r_texture_blanknormalmap;
8258 // make sure that if glow is going to be used, both textures are not NULL
8259 if (!t->backgroundglowtexture && t->glowtexture)
8260 t->backgroundglowtexture = r_texture_black;
8261 if (!t->glowtexture && t->backgroundglowtexture)
8262 t->glowtexture = r_texture_black;
8266 t->backgroundbasetexture = r_texture_white;
8267 t->backgroundnmaptexture = r_texture_blanknormalmap;
8268 t->backgroundglosstexture = r_texture_black;
8269 t->backgroundglowtexture = NULL;
8271 t->specularpower = r_shadow_glossexponent.value;
8272 // TODO: store reference values for these in the texture?
8273 t->specularscale = 0;
8274 if (r_shadow_gloss.integer > 0)
8276 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8278 if (r_shadow_glossintensity.value > 0)
8280 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8281 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8282 t->specularscale = r_shadow_glossintensity.value;
8285 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8287 t->glosstexture = r_texture_white;
8288 t->backgroundglosstexture = r_texture_white;
8289 t->specularscale = r_shadow_gloss2intensity.value;
8290 t->specularpower = r_shadow_gloss2exponent.value;
8293 t->specularscale *= t->specularscalemod;
8294 t->specularpower *= t->specularpowermod;
8295 t->rtlightambient = 0;
8297 // lightmaps mode looks bad with dlights using actual texturing, so turn
8298 // off the colormap and glossmap, but leave the normalmap on as it still
8299 // accurately represents the shading involved
8300 if (gl_lightmaps.integer)
8302 t->basetexture = r_texture_grey128;
8303 t->pantstexture = r_texture_black;
8304 t->shirttexture = r_texture_black;
8305 if (gl_lightmaps.integer < 2)
8306 t->nmaptexture = r_texture_blanknormalmap;
8307 t->glosstexture = r_texture_black;
8308 t->glowtexture = NULL;
8309 t->fogtexture = NULL;
8310 t->reflectmasktexture = NULL;
8311 t->backgroundbasetexture = NULL;
8312 if (gl_lightmaps.integer < 2)
8313 t->backgroundnmaptexture = r_texture_blanknormalmap;
8314 t->backgroundglosstexture = r_texture_black;
8315 t->backgroundglowtexture = NULL;
8316 t->specularscale = 0;
8317 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8320 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8321 VectorClear(t->dlightcolor);
8322 t->currentnumlayers = 0;
8323 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8325 int blendfunc1, blendfunc2;
8327 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8329 blendfunc1 = GL_SRC_ALPHA;
8330 blendfunc2 = GL_ONE;
8332 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8334 blendfunc1 = GL_SRC_ALPHA;
8335 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8337 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8339 blendfunc1 = t->customblendfunc[0];
8340 blendfunc2 = t->customblendfunc[1];
8344 blendfunc1 = GL_ONE;
8345 blendfunc2 = GL_ZERO;
8347 // don't colormod evilblend textures
8348 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8349 VectorSet(t->lightmapcolor, 1, 1, 1);
8350 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8351 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8353 // fullbright is not affected by r_refdef.lightmapintensity
8354 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]);
8355 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8356 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]);
8357 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8358 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]);
8362 vec3_t ambientcolor;
8364 // set the color tint used for lights affecting this surface
8365 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8367 // q3bsp has no lightmap updates, so the lightstylevalue that
8368 // would normally be baked into the lightmap must be
8369 // applied to the color
8370 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8371 if (model->type == mod_brushq3)
8372 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8373 colorscale *= r_refdef.lightmapintensity;
8374 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8375 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8376 // basic lit geometry
8377 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]);
8378 // add pants/shirt if needed
8379 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8380 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]);
8381 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8382 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]);
8383 // now add ambient passes if needed
8384 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8386 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]);
8387 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8388 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]);
8389 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8390 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]);
8393 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8394 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]);
8395 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8397 // if this is opaque use alpha blend which will darken the earlier
8400 // if this is an alpha blended material, all the earlier passes
8401 // were darkened by fog already, so we only need to add the fog
8402 // color ontop through the fog mask texture
8404 // if this is an additive blended material, all the earlier passes
8405 // were darkened by fog already, and we should not add fog color
8406 // (because the background was not darkened, there is no fog color
8407 // that was lost behind it).
8408 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]);
8412 return t->currentframe;
8415 rsurfacestate_t rsurface;
8417 void RSurf_ActiveWorldEntity(void)
8419 dp_model_t *model = r_refdef.scene.worldmodel;
8420 //if (rsurface.entity == r_refdef.scene.worldentity)
8422 rsurface.entity = r_refdef.scene.worldentity;
8423 rsurface.skeleton = NULL;
8424 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8425 rsurface.ent_skinnum = 0;
8426 rsurface.ent_qwskin = -1;
8427 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8428 rsurface.shadertime = r_refdef.scene.time;
8429 rsurface.matrix = identitymatrix;
8430 rsurface.inversematrix = identitymatrix;
8431 rsurface.matrixscale = 1;
8432 rsurface.inversematrixscale = 1;
8433 R_EntityMatrix(&identitymatrix);
8434 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8435 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8436 rsurface.fograngerecip = r_refdef.fograngerecip;
8437 rsurface.fogheightfade = r_refdef.fogheightfade;
8438 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8439 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8440 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8441 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8442 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8443 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8444 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8445 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8446 rsurface.colormod[3] = 1;
8447 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);
8448 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8449 rsurface.frameblend[0].lerp = 1;
8450 rsurface.ent_alttextures = false;
8451 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8452 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8453 rsurface.entityskeletaltransform3x4 = NULL;
8454 rsurface.entityskeletaltransform3x4buffer = NULL;
8455 rsurface.entityskeletaltransform3x4offset = 0;
8456 rsurface.entityskeletaltransform3x4size = 0;;
8457 rsurface.entityskeletalnumtransforms = 0;
8458 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8459 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8460 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8461 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8462 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8463 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8464 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8465 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8466 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8467 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8468 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8469 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8470 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8471 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8472 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8473 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8474 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8475 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8476 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8477 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8478 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8479 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8480 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8481 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8482 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8483 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8484 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8485 rsurface.modelelement3i = model->surfmesh.data_element3i;
8486 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8487 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8488 rsurface.modelelement3s = model->surfmesh.data_element3s;
8489 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8490 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8491 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8492 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8493 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8494 rsurface.modelsurfaces = model->data_surfaces;
8495 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8496 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8497 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8498 rsurface.modelgeneratedvertex = false;
8499 rsurface.batchgeneratedvertex = false;
8500 rsurface.batchfirstvertex = 0;
8501 rsurface.batchnumvertices = 0;
8502 rsurface.batchfirsttriangle = 0;
8503 rsurface.batchnumtriangles = 0;
8504 rsurface.batchvertex3f = NULL;
8505 rsurface.batchvertex3f_vertexbuffer = NULL;
8506 rsurface.batchvertex3f_bufferoffset = 0;
8507 rsurface.batchsvector3f = NULL;
8508 rsurface.batchsvector3f_vertexbuffer = NULL;
8509 rsurface.batchsvector3f_bufferoffset = 0;
8510 rsurface.batchtvector3f = NULL;
8511 rsurface.batchtvector3f_vertexbuffer = NULL;
8512 rsurface.batchtvector3f_bufferoffset = 0;
8513 rsurface.batchnormal3f = NULL;
8514 rsurface.batchnormal3f_vertexbuffer = NULL;
8515 rsurface.batchnormal3f_bufferoffset = 0;
8516 rsurface.batchlightmapcolor4f = NULL;
8517 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8518 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8519 rsurface.batchtexcoordtexture2f = NULL;
8520 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8521 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8522 rsurface.batchtexcoordlightmap2f = NULL;
8523 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8524 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8525 rsurface.batchskeletalindex4ub = NULL;
8526 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8527 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8528 rsurface.batchskeletalweight4ub = NULL;
8529 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8530 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8531 rsurface.batchvertexmesh = NULL;
8532 rsurface.batchvertexmesh_vertexbuffer = NULL;
8533 rsurface.batchvertexmesh_bufferoffset = 0;
8534 rsurface.batchelement3i = NULL;
8535 rsurface.batchelement3i_indexbuffer = NULL;
8536 rsurface.batchelement3i_bufferoffset = 0;
8537 rsurface.batchelement3s = NULL;
8538 rsurface.batchelement3s_indexbuffer = NULL;
8539 rsurface.batchelement3s_bufferoffset = 0;
8540 rsurface.passcolor4f = NULL;
8541 rsurface.passcolor4f_vertexbuffer = NULL;
8542 rsurface.passcolor4f_bufferoffset = 0;
8543 rsurface.forcecurrenttextureupdate = false;
8546 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8548 dp_model_t *model = ent->model;
8549 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8551 rsurface.entity = (entity_render_t *)ent;
8552 rsurface.skeleton = ent->skeleton;
8553 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8554 rsurface.ent_skinnum = ent->skinnum;
8555 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;
8556 rsurface.ent_flags = ent->flags;
8557 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8558 rsurface.matrix = ent->matrix;
8559 rsurface.inversematrix = ent->inversematrix;
8560 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8561 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8562 R_EntityMatrix(&rsurface.matrix);
8563 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8564 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8565 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8566 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8567 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8568 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8569 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8570 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8571 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8572 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8573 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8574 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8575 rsurface.colormod[3] = ent->alpha;
8576 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8577 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8578 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8579 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8580 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8581 if (ent->model->brush.submodel && !prepass)
8583 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8584 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8586 // if the animcache code decided it should use the shader path, skip the deform step
8587 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8588 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8589 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8590 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8591 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8592 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8594 if (ent->animcache_vertex3f)
8596 r_refdef.stats[r_stat_batch_entitycache_count]++;
8597 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8598 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8599 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8600 rsurface.modelvertex3f = ent->animcache_vertex3f;
8601 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8602 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8603 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8604 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8605 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8606 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8607 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8608 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8609 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8610 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8611 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8612 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8613 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8614 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8616 else if (wanttangents)
8618 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8619 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8620 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8621 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8622 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8623 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8624 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8625 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8626 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8627 rsurface.modelvertexmesh = NULL;
8628 rsurface.modelvertexmesh_vertexbuffer = NULL;
8629 rsurface.modelvertexmesh_bufferoffset = 0;
8630 rsurface.modelvertex3f_vertexbuffer = NULL;
8631 rsurface.modelvertex3f_bufferoffset = 0;
8632 rsurface.modelvertex3f_vertexbuffer = 0;
8633 rsurface.modelvertex3f_bufferoffset = 0;
8634 rsurface.modelsvector3f_vertexbuffer = 0;
8635 rsurface.modelsvector3f_bufferoffset = 0;
8636 rsurface.modeltvector3f_vertexbuffer = 0;
8637 rsurface.modeltvector3f_bufferoffset = 0;
8638 rsurface.modelnormal3f_vertexbuffer = 0;
8639 rsurface.modelnormal3f_bufferoffset = 0;
8641 else if (wantnormals)
8643 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8644 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8645 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8646 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8647 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8648 rsurface.modelsvector3f = NULL;
8649 rsurface.modeltvector3f = NULL;
8650 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8651 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8652 rsurface.modelvertexmesh = NULL;
8653 rsurface.modelvertexmesh_vertexbuffer = NULL;
8654 rsurface.modelvertexmesh_bufferoffset = 0;
8655 rsurface.modelvertex3f_vertexbuffer = NULL;
8656 rsurface.modelvertex3f_bufferoffset = 0;
8657 rsurface.modelvertex3f_vertexbuffer = 0;
8658 rsurface.modelvertex3f_bufferoffset = 0;
8659 rsurface.modelsvector3f_vertexbuffer = 0;
8660 rsurface.modelsvector3f_bufferoffset = 0;
8661 rsurface.modeltvector3f_vertexbuffer = 0;
8662 rsurface.modeltvector3f_bufferoffset = 0;
8663 rsurface.modelnormal3f_vertexbuffer = 0;
8664 rsurface.modelnormal3f_bufferoffset = 0;
8668 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8669 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8670 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8671 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8672 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8673 rsurface.modelsvector3f = NULL;
8674 rsurface.modeltvector3f = NULL;
8675 rsurface.modelnormal3f = NULL;
8676 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8677 rsurface.modelvertexmesh = NULL;
8678 rsurface.modelvertexmesh_vertexbuffer = NULL;
8679 rsurface.modelvertexmesh_bufferoffset = 0;
8680 rsurface.modelvertex3f_vertexbuffer = NULL;
8681 rsurface.modelvertex3f_bufferoffset = 0;
8682 rsurface.modelvertex3f_vertexbuffer = 0;
8683 rsurface.modelvertex3f_bufferoffset = 0;
8684 rsurface.modelsvector3f_vertexbuffer = 0;
8685 rsurface.modelsvector3f_bufferoffset = 0;
8686 rsurface.modeltvector3f_vertexbuffer = 0;
8687 rsurface.modeltvector3f_bufferoffset = 0;
8688 rsurface.modelnormal3f_vertexbuffer = 0;
8689 rsurface.modelnormal3f_bufferoffset = 0;
8691 rsurface.modelgeneratedvertex = true;
8695 if (rsurface.entityskeletaltransform3x4)
8697 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8698 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8699 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8700 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8704 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8705 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8706 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8707 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8709 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8710 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8711 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8712 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8713 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8714 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8715 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8716 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8717 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8718 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8719 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8720 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8721 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8722 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8723 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8724 rsurface.modelgeneratedvertex = false;
8726 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8727 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8728 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8729 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8730 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8731 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8732 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8733 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8734 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8735 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8736 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8737 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8738 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8739 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8740 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8741 rsurface.modelelement3i = model->surfmesh.data_element3i;
8742 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8743 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8744 rsurface.modelelement3s = model->surfmesh.data_element3s;
8745 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8746 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8747 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8748 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8749 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8750 rsurface.modelsurfaces = model->data_surfaces;
8751 rsurface.batchgeneratedvertex = false;
8752 rsurface.batchfirstvertex = 0;
8753 rsurface.batchnumvertices = 0;
8754 rsurface.batchfirsttriangle = 0;
8755 rsurface.batchnumtriangles = 0;
8756 rsurface.batchvertex3f = NULL;
8757 rsurface.batchvertex3f_vertexbuffer = NULL;
8758 rsurface.batchvertex3f_bufferoffset = 0;
8759 rsurface.batchsvector3f = NULL;
8760 rsurface.batchsvector3f_vertexbuffer = NULL;
8761 rsurface.batchsvector3f_bufferoffset = 0;
8762 rsurface.batchtvector3f = NULL;
8763 rsurface.batchtvector3f_vertexbuffer = NULL;
8764 rsurface.batchtvector3f_bufferoffset = 0;
8765 rsurface.batchnormal3f = NULL;
8766 rsurface.batchnormal3f_vertexbuffer = NULL;
8767 rsurface.batchnormal3f_bufferoffset = 0;
8768 rsurface.batchlightmapcolor4f = NULL;
8769 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8770 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8771 rsurface.batchtexcoordtexture2f = NULL;
8772 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8773 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8774 rsurface.batchtexcoordlightmap2f = NULL;
8775 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8776 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8777 rsurface.batchskeletalindex4ub = NULL;
8778 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8779 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8780 rsurface.batchskeletalweight4ub = NULL;
8781 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8782 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8783 rsurface.batchvertexmesh = NULL;
8784 rsurface.batchvertexmesh_vertexbuffer = NULL;
8785 rsurface.batchvertexmesh_bufferoffset = 0;
8786 rsurface.batchelement3i = NULL;
8787 rsurface.batchelement3i_indexbuffer = NULL;
8788 rsurface.batchelement3i_bufferoffset = 0;
8789 rsurface.batchelement3s = NULL;
8790 rsurface.batchelement3s_indexbuffer = NULL;
8791 rsurface.batchelement3s_bufferoffset = 0;
8792 rsurface.passcolor4f = NULL;
8793 rsurface.passcolor4f_vertexbuffer = NULL;
8794 rsurface.passcolor4f_bufferoffset = 0;
8795 rsurface.forcecurrenttextureupdate = false;
8798 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)
8800 rsurface.entity = r_refdef.scene.worldentity;
8801 rsurface.skeleton = NULL;
8802 rsurface.ent_skinnum = 0;
8803 rsurface.ent_qwskin = -1;
8804 rsurface.ent_flags = entflags;
8805 rsurface.shadertime = r_refdef.scene.time - shadertime;
8806 rsurface.modelnumvertices = numvertices;
8807 rsurface.modelnumtriangles = numtriangles;
8808 rsurface.matrix = *matrix;
8809 rsurface.inversematrix = *inversematrix;
8810 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8811 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8812 R_EntityMatrix(&rsurface.matrix);
8813 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8814 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8815 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8816 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8817 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8818 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8819 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8820 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8821 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8822 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8823 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8824 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8825 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);
8826 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8827 rsurface.frameblend[0].lerp = 1;
8828 rsurface.ent_alttextures = false;
8829 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8830 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8831 rsurface.entityskeletaltransform3x4 = NULL;
8832 rsurface.entityskeletaltransform3x4buffer = NULL;
8833 rsurface.entityskeletaltransform3x4offset = 0;
8834 rsurface.entityskeletaltransform3x4size = 0;
8835 rsurface.entityskeletalnumtransforms = 0;
8836 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8837 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8838 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8839 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8842 rsurface.modelvertex3f = (float *)vertex3f;
8843 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8844 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8845 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8847 else if (wantnormals)
8849 rsurface.modelvertex3f = (float *)vertex3f;
8850 rsurface.modelsvector3f = NULL;
8851 rsurface.modeltvector3f = NULL;
8852 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8856 rsurface.modelvertex3f = (float *)vertex3f;
8857 rsurface.modelsvector3f = NULL;
8858 rsurface.modeltvector3f = NULL;
8859 rsurface.modelnormal3f = NULL;
8861 rsurface.modelvertexmesh = NULL;
8862 rsurface.modelvertexmesh_vertexbuffer = NULL;
8863 rsurface.modelvertexmesh_bufferoffset = 0;
8864 rsurface.modelvertex3f_vertexbuffer = 0;
8865 rsurface.modelvertex3f_bufferoffset = 0;
8866 rsurface.modelsvector3f_vertexbuffer = 0;
8867 rsurface.modelsvector3f_bufferoffset = 0;
8868 rsurface.modeltvector3f_vertexbuffer = 0;
8869 rsurface.modeltvector3f_bufferoffset = 0;
8870 rsurface.modelnormal3f_vertexbuffer = 0;
8871 rsurface.modelnormal3f_bufferoffset = 0;
8872 rsurface.modelgeneratedvertex = true;
8873 rsurface.modellightmapcolor4f = (float *)color4f;
8874 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8875 rsurface.modellightmapcolor4f_bufferoffset = 0;
8876 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8877 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8878 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8879 rsurface.modeltexcoordlightmap2f = NULL;
8880 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8881 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8882 rsurface.modelskeletalindex4ub = NULL;
8883 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8884 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8885 rsurface.modelskeletalweight4ub = NULL;
8886 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8887 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8888 rsurface.modelelement3i = (int *)element3i;
8889 rsurface.modelelement3i_indexbuffer = NULL;
8890 rsurface.modelelement3i_bufferoffset = 0;
8891 rsurface.modelelement3s = (unsigned short *)element3s;
8892 rsurface.modelelement3s_indexbuffer = NULL;
8893 rsurface.modelelement3s_bufferoffset = 0;
8894 rsurface.modellightmapoffsets = NULL;
8895 rsurface.modelsurfaces = NULL;
8896 rsurface.batchgeneratedvertex = false;
8897 rsurface.batchfirstvertex = 0;
8898 rsurface.batchnumvertices = 0;
8899 rsurface.batchfirsttriangle = 0;
8900 rsurface.batchnumtriangles = 0;
8901 rsurface.batchvertex3f = NULL;
8902 rsurface.batchvertex3f_vertexbuffer = NULL;
8903 rsurface.batchvertex3f_bufferoffset = 0;
8904 rsurface.batchsvector3f = NULL;
8905 rsurface.batchsvector3f_vertexbuffer = NULL;
8906 rsurface.batchsvector3f_bufferoffset = 0;
8907 rsurface.batchtvector3f = NULL;
8908 rsurface.batchtvector3f_vertexbuffer = NULL;
8909 rsurface.batchtvector3f_bufferoffset = 0;
8910 rsurface.batchnormal3f = NULL;
8911 rsurface.batchnormal3f_vertexbuffer = NULL;
8912 rsurface.batchnormal3f_bufferoffset = 0;
8913 rsurface.batchlightmapcolor4f = NULL;
8914 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8915 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8916 rsurface.batchtexcoordtexture2f = NULL;
8917 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8918 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8919 rsurface.batchtexcoordlightmap2f = NULL;
8920 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8921 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8922 rsurface.batchskeletalindex4ub = NULL;
8923 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8924 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8925 rsurface.batchskeletalweight4ub = NULL;
8926 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8927 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8928 rsurface.batchvertexmesh = NULL;
8929 rsurface.batchvertexmesh_vertexbuffer = NULL;
8930 rsurface.batchvertexmesh_bufferoffset = 0;
8931 rsurface.batchelement3i = NULL;
8932 rsurface.batchelement3i_indexbuffer = NULL;
8933 rsurface.batchelement3i_bufferoffset = 0;
8934 rsurface.batchelement3s = NULL;
8935 rsurface.batchelement3s_indexbuffer = NULL;
8936 rsurface.batchelement3s_bufferoffset = 0;
8937 rsurface.passcolor4f = NULL;
8938 rsurface.passcolor4f_vertexbuffer = NULL;
8939 rsurface.passcolor4f_bufferoffset = 0;
8940 rsurface.forcecurrenttextureupdate = true;
8942 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8944 if ((wantnormals || wanttangents) && !normal3f)
8946 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8947 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8949 if (wanttangents && !svector3f)
8951 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8952 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8953 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8958 float RSurf_FogPoint(const float *v)
8960 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8961 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8962 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8963 float FogHeightFade = r_refdef.fogheightfade;
8965 unsigned int fogmasktableindex;
8966 if (r_refdef.fogplaneviewabove)
8967 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8969 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8970 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8971 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8974 float RSurf_FogVertex(const float *v)
8976 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8977 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8978 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8979 float FogHeightFade = rsurface.fogheightfade;
8981 unsigned int fogmasktableindex;
8982 if (r_refdef.fogplaneviewabove)
8983 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8985 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8986 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8987 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8990 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8993 for (i = 0;i < numelements;i++)
8994 outelement3i[i] = inelement3i[i] + adjust;
8997 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8998 extern cvar_t gl_vbo;
8999 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9007 int surfacefirsttriangle;
9008 int surfacenumtriangles;
9009 int surfacefirstvertex;
9010 int surfaceendvertex;
9011 int surfacenumvertices;
9012 int batchnumsurfaces = texturenumsurfaces;
9013 int batchnumvertices;
9014 int batchnumtriangles;
9018 qboolean dynamicvertex;
9022 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9025 q3shaderinfo_deform_t *deform;
9026 const msurface_t *surface, *firstsurface;
9027 r_vertexmesh_t *vertexmesh;
9028 if (!texturenumsurfaces)
9030 // find vertex range of this surface batch
9032 firstsurface = texturesurfacelist[0];
9033 firsttriangle = firstsurface->num_firsttriangle;
9034 batchnumvertices = 0;
9035 batchnumtriangles = 0;
9036 firstvertex = endvertex = firstsurface->num_firstvertex;
9037 for (i = 0;i < texturenumsurfaces;i++)
9039 surface = texturesurfacelist[i];
9040 if (surface != firstsurface + i)
9042 surfacefirstvertex = surface->num_firstvertex;
9043 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9044 surfacenumvertices = surface->num_vertices;
9045 surfacenumtriangles = surface->num_triangles;
9046 if (firstvertex > surfacefirstvertex)
9047 firstvertex = surfacefirstvertex;
9048 if (endvertex < surfaceendvertex)
9049 endvertex = surfaceendvertex;
9050 batchnumvertices += surfacenumvertices;
9051 batchnumtriangles += surfacenumtriangles;
9054 r_refdef.stats[r_stat_batch_batches]++;
9056 r_refdef.stats[r_stat_batch_withgaps]++;
9057 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9058 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9059 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9061 // we now know the vertex range used, and if there are any gaps in it
9062 rsurface.batchfirstvertex = firstvertex;
9063 rsurface.batchnumvertices = endvertex - firstvertex;
9064 rsurface.batchfirsttriangle = firsttriangle;
9065 rsurface.batchnumtriangles = batchnumtriangles;
9067 // this variable holds flags for which properties have been updated that
9068 // may require regenerating vertexmesh array...
9071 // check if any dynamic vertex processing must occur
9072 dynamicvertex = false;
9074 // a cvar to force the dynamic vertex path to be taken, for debugging
9075 if (r_batch_debugdynamicvertexpath.integer)
9079 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9080 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9081 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9082 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9084 dynamicvertex = true;
9087 // if there is a chance of animated vertex colors, it's a dynamic batch
9088 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9092 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9093 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9094 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9095 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9097 dynamicvertex = true;
9098 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9101 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9103 switch (deform->deform)
9106 case Q3DEFORM_PROJECTIONSHADOW:
9107 case Q3DEFORM_TEXT0:
9108 case Q3DEFORM_TEXT1:
9109 case Q3DEFORM_TEXT2:
9110 case Q3DEFORM_TEXT3:
9111 case Q3DEFORM_TEXT4:
9112 case Q3DEFORM_TEXT5:
9113 case Q3DEFORM_TEXT6:
9114 case Q3DEFORM_TEXT7:
9117 case Q3DEFORM_AUTOSPRITE:
9120 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9121 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9122 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9123 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9125 dynamicvertex = true;
9126 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9127 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9129 case Q3DEFORM_AUTOSPRITE2:
9132 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9133 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9134 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9135 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9137 dynamicvertex = true;
9138 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9139 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9141 case Q3DEFORM_NORMAL:
9144 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9145 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9146 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9147 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9149 dynamicvertex = true;
9150 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9151 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9154 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9155 break; // if wavefunc is a nop, ignore this transform
9158 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9159 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9160 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9161 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9163 dynamicvertex = true;
9164 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9165 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9167 case Q3DEFORM_BULGE:
9170 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9171 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9172 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9173 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9175 dynamicvertex = true;
9176 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9177 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9180 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9181 break; // if wavefunc is a nop, ignore this transform
9184 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9185 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9186 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9187 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9189 dynamicvertex = true;
9190 batchneed |= BATCHNEED_ARRAY_VERTEX;
9191 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9195 switch(rsurface.texture->tcgen.tcgen)
9198 case Q3TCGEN_TEXTURE:
9200 case Q3TCGEN_LIGHTMAP:
9203 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9204 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9205 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9206 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9208 dynamicvertex = true;
9209 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9210 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9212 case Q3TCGEN_VECTOR:
9215 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9216 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9217 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9218 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9220 dynamicvertex = true;
9221 batchneed |= BATCHNEED_ARRAY_VERTEX;
9222 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9224 case Q3TCGEN_ENVIRONMENT:
9227 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9228 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9229 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9230 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9232 dynamicvertex = true;
9233 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9234 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9237 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9241 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9242 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9243 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9244 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9246 dynamicvertex = true;
9247 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9248 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9251 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9255 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9256 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9257 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9258 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9260 dynamicvertex = true;
9261 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9264 // when the model data has no vertex buffer (dynamic mesh), we need to
9266 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9267 batchneed |= BATCHNEED_NOGAPS;
9269 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9270 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9271 // we ensure this by treating the vertex batch as dynamic...
9272 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9276 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9277 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9278 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9279 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9281 dynamicvertex = true;
9286 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9287 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9288 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9289 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9290 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9291 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9292 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9293 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9296 // if needsupdate, we have to do a dynamic vertex batch for sure
9297 if (needsupdate & batchneed)
9301 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9302 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9303 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9304 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9306 dynamicvertex = true;
9309 // see if we need to build vertexmesh from arrays
9310 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9314 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9315 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9316 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9317 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9319 dynamicvertex = true;
9322 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9323 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9324 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9326 rsurface.batchvertex3f = rsurface.modelvertex3f;
9327 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9328 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9329 rsurface.batchsvector3f = rsurface.modelsvector3f;
9330 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9331 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9332 rsurface.batchtvector3f = rsurface.modeltvector3f;
9333 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9334 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9335 rsurface.batchnormal3f = rsurface.modelnormal3f;
9336 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9337 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9338 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9339 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9340 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9341 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9342 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9343 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9344 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9345 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9346 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9347 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9348 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9349 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9350 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9351 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9352 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9353 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9354 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9355 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9356 rsurface.batchelement3i = rsurface.modelelement3i;
9357 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9358 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9359 rsurface.batchelement3s = rsurface.modelelement3s;
9360 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9361 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9362 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9363 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9364 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9365 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9366 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9368 // if any dynamic vertex processing has to occur in software, we copy the
9369 // entire surface list together before processing to rebase the vertices
9370 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9372 // if any gaps exist and we do not have a static vertex buffer, we have to
9373 // copy the surface list together to avoid wasting upload bandwidth on the
9374 // vertices in the gaps.
9376 // if gaps exist and we have a static vertex buffer, we can choose whether
9377 // to combine the index buffer ranges into one dynamic index buffer or
9378 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9380 // in many cases the batch is reduced to one draw call.
9382 rsurface.batchmultidraw = false;
9383 rsurface.batchmultidrawnumsurfaces = 0;
9384 rsurface.batchmultidrawsurfacelist = NULL;
9388 // static vertex data, just set pointers...
9389 rsurface.batchgeneratedvertex = false;
9390 // if there are gaps, we want to build a combined index buffer,
9391 // otherwise use the original static buffer with an appropriate offset
9394 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9395 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9396 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9397 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9398 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9400 rsurface.batchmultidraw = true;
9401 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9402 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9405 // build a new triangle elements array for this batch
9406 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9407 rsurface.batchfirsttriangle = 0;
9409 for (i = 0;i < texturenumsurfaces;i++)
9411 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9412 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9413 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9414 numtriangles += surfacenumtriangles;
9416 rsurface.batchelement3i_indexbuffer = NULL;
9417 rsurface.batchelement3i_bufferoffset = 0;
9418 rsurface.batchelement3s = NULL;
9419 rsurface.batchelement3s_indexbuffer = NULL;
9420 rsurface.batchelement3s_bufferoffset = 0;
9421 if (endvertex <= 65536)
9423 // make a 16bit (unsigned short) index array if possible
9424 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9425 for (i = 0;i < numtriangles*3;i++)
9426 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9428 // upload buffer data for the copytriangles batch
9429 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9431 if (rsurface.batchelement3s)
9432 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9433 else if (rsurface.batchelement3i)
9434 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9439 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9440 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9441 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9442 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9447 // something needs software processing, do it for real...
9448 // we only directly handle separate array data in this case and then
9449 // generate interleaved data if needed...
9450 rsurface.batchgeneratedvertex = true;
9451 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9452 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9453 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9454 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9456 // now copy the vertex data into a combined array and make an index array
9457 // (this is what Quake3 does all the time)
9458 // we also apply any skeletal animation here that would have been done in
9459 // the vertex shader, because most of the dynamic vertex animation cases
9460 // need actual vertex positions and normals
9461 //if (dynamicvertex)
9463 rsurface.batchvertexmesh = NULL;
9464 rsurface.batchvertexmesh_vertexbuffer = NULL;
9465 rsurface.batchvertexmesh_bufferoffset = 0;
9466 rsurface.batchvertex3f = NULL;
9467 rsurface.batchvertex3f_vertexbuffer = NULL;
9468 rsurface.batchvertex3f_bufferoffset = 0;
9469 rsurface.batchsvector3f = NULL;
9470 rsurface.batchsvector3f_vertexbuffer = NULL;
9471 rsurface.batchsvector3f_bufferoffset = 0;
9472 rsurface.batchtvector3f = NULL;
9473 rsurface.batchtvector3f_vertexbuffer = NULL;
9474 rsurface.batchtvector3f_bufferoffset = 0;
9475 rsurface.batchnormal3f = NULL;
9476 rsurface.batchnormal3f_vertexbuffer = NULL;
9477 rsurface.batchnormal3f_bufferoffset = 0;
9478 rsurface.batchlightmapcolor4f = NULL;
9479 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9480 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9481 rsurface.batchtexcoordtexture2f = NULL;
9482 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9483 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9484 rsurface.batchtexcoordlightmap2f = NULL;
9485 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9486 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9487 rsurface.batchskeletalindex4ub = NULL;
9488 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9489 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9490 rsurface.batchskeletalweight4ub = NULL;
9491 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9492 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9493 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9494 rsurface.batchelement3i_indexbuffer = NULL;
9495 rsurface.batchelement3i_bufferoffset = 0;
9496 rsurface.batchelement3s = NULL;
9497 rsurface.batchelement3s_indexbuffer = NULL;
9498 rsurface.batchelement3s_bufferoffset = 0;
9499 rsurface.batchskeletaltransform3x4buffer = NULL;
9500 rsurface.batchskeletaltransform3x4offset = 0;
9501 rsurface.batchskeletaltransform3x4size = 0;
9502 // we'll only be setting up certain arrays as needed
9503 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9504 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9505 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9506 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9507 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9508 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9509 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9511 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9512 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9514 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9515 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9516 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9517 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9518 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9519 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9520 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9522 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9523 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9527 for (i = 0;i < texturenumsurfaces;i++)
9529 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9530 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9531 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9532 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9533 // copy only the data requested
9534 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9535 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9536 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9538 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9540 if (rsurface.batchvertex3f)
9541 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9543 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9545 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9547 if (rsurface.modelnormal3f)
9548 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9550 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9552 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9554 if (rsurface.modelsvector3f)
9556 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9557 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9561 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9562 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9565 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9567 if (rsurface.modellightmapcolor4f)
9568 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9570 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9572 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9574 if (rsurface.modeltexcoordtexture2f)
9575 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9577 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9579 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9581 if (rsurface.modeltexcoordlightmap2f)
9582 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9584 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9586 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9588 if (rsurface.modelskeletalindex4ub)
9590 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9591 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9595 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9596 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9597 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9598 for (j = 0;j < surfacenumvertices;j++)
9603 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9604 numvertices += surfacenumvertices;
9605 numtriangles += surfacenumtriangles;
9608 // generate a 16bit index array as well if possible
9609 // (in general, dynamic batches fit)
9610 if (numvertices <= 65536)
9612 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9613 for (i = 0;i < numtriangles*3;i++)
9614 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9617 // since we've copied everything, the batch now starts at 0
9618 rsurface.batchfirstvertex = 0;
9619 rsurface.batchnumvertices = batchnumvertices;
9620 rsurface.batchfirsttriangle = 0;
9621 rsurface.batchnumtriangles = batchnumtriangles;
9624 // apply skeletal animation that would have been done in the vertex shader
9625 if (rsurface.batchskeletaltransform3x4)
9627 const unsigned char *si;
9628 const unsigned char *sw;
9630 const float *b = rsurface.batchskeletaltransform3x4;
9631 float *vp, *vs, *vt, *vn;
9633 float m[3][4], n[3][4];
9634 float tp[3], ts[3], tt[3], tn[3];
9635 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9636 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9637 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9638 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9639 si = rsurface.batchskeletalindex4ub;
9640 sw = rsurface.batchskeletalweight4ub;
9641 vp = rsurface.batchvertex3f;
9642 vs = rsurface.batchsvector3f;
9643 vt = rsurface.batchtvector3f;
9644 vn = rsurface.batchnormal3f;
9645 memset(m[0], 0, sizeof(m));
9646 memset(n[0], 0, sizeof(n));
9647 for (i = 0;i < batchnumvertices;i++)
9649 t[0] = b + si[0]*12;
9652 // common case - only one matrix
9666 else if (sw[2] + sw[3])
9669 t[1] = b + si[1]*12;
9670 t[2] = b + si[2]*12;
9671 t[3] = b + si[3]*12;
9672 w[0] = sw[0] * (1.0f / 255.0f);
9673 w[1] = sw[1] * (1.0f / 255.0f);
9674 w[2] = sw[2] * (1.0f / 255.0f);
9675 w[3] = sw[3] * (1.0f / 255.0f);
9676 // blend the matrices
9677 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9678 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9679 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9680 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9681 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9682 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9683 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9684 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9685 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9686 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9687 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9688 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9693 t[1] = b + si[1]*12;
9694 w[0] = sw[0] * (1.0f / 255.0f);
9695 w[1] = sw[1] * (1.0f / 255.0f);
9696 // blend the matrices
9697 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9698 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9699 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9700 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9701 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9702 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9703 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9704 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9705 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9706 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9707 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9708 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9712 // modify the vertex
9714 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9715 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9716 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9720 // the normal transformation matrix is a set of cross products...
9721 CrossProduct(m[1], m[2], n[0]);
9722 CrossProduct(m[2], m[0], n[1]);
9723 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9725 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9726 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9727 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9728 VectorNormalize(vn);
9733 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9734 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9735 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9736 VectorNormalize(vs);
9739 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9740 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9741 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9742 VectorNormalize(vt);
9747 rsurface.batchskeletaltransform3x4 = NULL;
9748 rsurface.batchskeletalnumtransforms = 0;
9751 // q1bsp surfaces rendered in vertex color mode have to have colors
9752 // calculated based on lightstyles
9753 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9755 // generate color arrays for the surfaces in this list
9760 const unsigned char *lm;
9761 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9762 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9763 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9765 for (i = 0;i < texturenumsurfaces;i++)
9767 surface = texturesurfacelist[i];
9768 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9769 surfacenumvertices = surface->num_vertices;
9770 if (surface->lightmapinfo->samples)
9772 for (j = 0;j < surfacenumvertices;j++)
9774 lm = surface->lightmapinfo->samples + offsets[j];
9775 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9776 VectorScale(lm, scale, c);
9777 if (surface->lightmapinfo->styles[1] != 255)
9779 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9781 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9782 VectorMA(c, scale, lm, c);
9783 if (surface->lightmapinfo->styles[2] != 255)
9786 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9787 VectorMA(c, scale, lm, c);
9788 if (surface->lightmapinfo->styles[3] != 255)
9791 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9792 VectorMA(c, scale, lm, c);
9799 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);
9805 for (j = 0;j < surfacenumvertices;j++)
9807 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9814 // if vertices are deformed (sprite flares and things in maps, possibly
9815 // water waves, bulges and other deformations), modify the copied vertices
9817 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9819 switch (deform->deform)
9822 case Q3DEFORM_PROJECTIONSHADOW:
9823 case Q3DEFORM_TEXT0:
9824 case Q3DEFORM_TEXT1:
9825 case Q3DEFORM_TEXT2:
9826 case Q3DEFORM_TEXT3:
9827 case Q3DEFORM_TEXT4:
9828 case Q3DEFORM_TEXT5:
9829 case Q3DEFORM_TEXT6:
9830 case Q3DEFORM_TEXT7:
9833 case Q3DEFORM_AUTOSPRITE:
9834 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9835 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9836 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9837 VectorNormalize(newforward);
9838 VectorNormalize(newright);
9839 VectorNormalize(newup);
9840 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9841 // rsurface.batchvertex3f_vertexbuffer = NULL;
9842 // rsurface.batchvertex3f_bufferoffset = 0;
9843 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9844 // rsurface.batchsvector3f_vertexbuffer = NULL;
9845 // rsurface.batchsvector3f_bufferoffset = 0;
9846 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9847 // rsurface.batchtvector3f_vertexbuffer = NULL;
9848 // rsurface.batchtvector3f_bufferoffset = 0;
9849 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9850 // rsurface.batchnormal3f_vertexbuffer = NULL;
9851 // rsurface.batchnormal3f_bufferoffset = 0;
9852 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9853 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9854 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9855 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9856 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);
9857 // a single autosprite surface can contain multiple sprites...
9858 for (j = 0;j < batchnumvertices - 3;j += 4)
9860 VectorClear(center);
9861 for (i = 0;i < 4;i++)
9862 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9863 VectorScale(center, 0.25f, center);
9864 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9865 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9866 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9867 for (i = 0;i < 4;i++)
9869 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9870 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9873 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9874 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9875 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);
9877 case Q3DEFORM_AUTOSPRITE2:
9878 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9879 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9880 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9881 VectorNormalize(newforward);
9882 VectorNormalize(newright);
9883 VectorNormalize(newup);
9884 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9885 // rsurface.batchvertex3f_vertexbuffer = NULL;
9886 // rsurface.batchvertex3f_bufferoffset = 0;
9888 const float *v1, *v2;
9898 memset(shortest, 0, sizeof(shortest));
9899 // a single autosprite surface can contain multiple sprites...
9900 for (j = 0;j < batchnumvertices - 3;j += 4)
9902 VectorClear(center);
9903 for (i = 0;i < 4;i++)
9904 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9905 VectorScale(center, 0.25f, center);
9906 // find the two shortest edges, then use them to define the
9907 // axis vectors for rotating around the central axis
9908 for (i = 0;i < 6;i++)
9910 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9911 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9912 l = VectorDistance2(v1, v2);
9913 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9915 l += (1.0f / 1024.0f);
9916 if (shortest[0].length2 > l || i == 0)
9918 shortest[1] = shortest[0];
9919 shortest[0].length2 = l;
9920 shortest[0].v1 = v1;
9921 shortest[0].v2 = v2;
9923 else if (shortest[1].length2 > l || i == 1)
9925 shortest[1].length2 = l;
9926 shortest[1].v1 = v1;
9927 shortest[1].v2 = v2;
9930 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9931 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9932 // this calculates the right vector from the shortest edge
9933 // and the up vector from the edge midpoints
9934 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9935 VectorNormalize(right);
9936 VectorSubtract(end, start, up);
9937 VectorNormalize(up);
9938 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9939 VectorSubtract(rsurface.localvieworigin, center, forward);
9940 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9941 VectorNegate(forward, forward);
9942 VectorReflect(forward, 0, up, forward);
9943 VectorNormalize(forward);
9944 CrossProduct(up, forward, newright);
9945 VectorNormalize(newright);
9946 // rotate the quad around the up axis vector, this is made
9947 // especially easy by the fact we know the quad is flat,
9948 // so we only have to subtract the center position and
9949 // measure distance along the right vector, and then
9950 // multiply that by the newright vector and add back the
9952 // we also need to subtract the old position to undo the
9953 // displacement from the center, which we do with a
9954 // DotProduct, the subtraction/addition of center is also
9955 // optimized into DotProducts here
9956 l = DotProduct(right, center);
9957 for (i = 0;i < 4;i++)
9959 v1 = rsurface.batchvertex3f + 3*(j+i);
9960 f = DotProduct(right, v1) - l;
9961 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9965 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9967 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9968 // rsurface.batchnormal3f_vertexbuffer = NULL;
9969 // rsurface.batchnormal3f_bufferoffset = 0;
9970 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9972 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9974 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9975 // rsurface.batchsvector3f_vertexbuffer = NULL;
9976 // rsurface.batchsvector3f_bufferoffset = 0;
9977 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9978 // rsurface.batchtvector3f_vertexbuffer = NULL;
9979 // rsurface.batchtvector3f_bufferoffset = 0;
9980 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);
9983 case Q3DEFORM_NORMAL:
9984 // deform the normals to make reflections wavey
9985 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9986 rsurface.batchnormal3f_vertexbuffer = NULL;
9987 rsurface.batchnormal3f_bufferoffset = 0;
9988 for (j = 0;j < batchnumvertices;j++)
9991 float *normal = rsurface.batchnormal3f + 3*j;
9992 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9993 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9994 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9995 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9996 VectorNormalize(normal);
9998 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10000 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10001 // rsurface.batchsvector3f_vertexbuffer = NULL;
10002 // rsurface.batchsvector3f_bufferoffset = 0;
10003 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10004 // rsurface.batchtvector3f_vertexbuffer = NULL;
10005 // rsurface.batchtvector3f_bufferoffset = 0;
10006 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);
10009 case Q3DEFORM_WAVE:
10010 // deform vertex array to make wavey water and flags and such
10011 waveparms[0] = deform->waveparms[0];
10012 waveparms[1] = deform->waveparms[1];
10013 waveparms[2] = deform->waveparms[2];
10014 waveparms[3] = deform->waveparms[3];
10015 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10016 break; // if wavefunc is a nop, don't make a dynamic vertex array
10017 // this is how a divisor of vertex influence on deformation
10018 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10019 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10020 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10021 // rsurface.batchvertex3f_vertexbuffer = NULL;
10022 // rsurface.batchvertex3f_bufferoffset = 0;
10023 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10024 // rsurface.batchnormal3f_vertexbuffer = NULL;
10025 // rsurface.batchnormal3f_bufferoffset = 0;
10026 for (j = 0;j < batchnumvertices;j++)
10028 // if the wavefunc depends on time, evaluate it per-vertex
10031 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10032 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10034 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10036 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10037 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10038 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10040 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10041 // rsurface.batchsvector3f_vertexbuffer = NULL;
10042 // rsurface.batchsvector3f_bufferoffset = 0;
10043 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10044 // rsurface.batchtvector3f_vertexbuffer = NULL;
10045 // rsurface.batchtvector3f_bufferoffset = 0;
10046 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);
10049 case Q3DEFORM_BULGE:
10050 // deform vertex array to make the surface have moving bulges
10051 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10052 // rsurface.batchvertex3f_vertexbuffer = NULL;
10053 // rsurface.batchvertex3f_bufferoffset = 0;
10054 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10055 // rsurface.batchnormal3f_vertexbuffer = NULL;
10056 // rsurface.batchnormal3f_bufferoffset = 0;
10057 for (j = 0;j < batchnumvertices;j++)
10059 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10060 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10062 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10063 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10064 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10066 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10067 // rsurface.batchsvector3f_vertexbuffer = NULL;
10068 // rsurface.batchsvector3f_bufferoffset = 0;
10069 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10070 // rsurface.batchtvector3f_vertexbuffer = NULL;
10071 // rsurface.batchtvector3f_bufferoffset = 0;
10072 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);
10075 case Q3DEFORM_MOVE:
10076 // deform vertex array
10077 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10078 break; // if wavefunc is a nop, don't make a dynamic vertex array
10079 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10080 VectorScale(deform->parms, scale, waveparms);
10081 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10082 // rsurface.batchvertex3f_vertexbuffer = NULL;
10083 // rsurface.batchvertex3f_bufferoffset = 0;
10084 for (j = 0;j < batchnumvertices;j++)
10085 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10090 // generate texcoords based on the chosen texcoord source
10091 switch(rsurface.texture->tcgen.tcgen)
10094 case Q3TCGEN_TEXTURE:
10096 case Q3TCGEN_LIGHTMAP:
10097 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10098 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10099 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10100 if (rsurface.batchtexcoordlightmap2f)
10101 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10103 case Q3TCGEN_VECTOR:
10104 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10105 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10106 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10107 for (j = 0;j < batchnumvertices;j++)
10109 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10110 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10113 case Q3TCGEN_ENVIRONMENT:
10114 // make environment reflections using a spheremap
10115 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10116 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10117 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10118 for (j = 0;j < batchnumvertices;j++)
10120 // identical to Q3A's method, but executed in worldspace so
10121 // carried models can be shiny too
10123 float viewer[3], d, reflected[3], worldreflected[3];
10125 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10126 // VectorNormalize(viewer);
10128 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10130 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10131 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10132 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10133 // note: this is proportinal to viewer, so we can normalize later
10135 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10136 VectorNormalize(worldreflected);
10138 // note: this sphere map only uses world x and z!
10139 // so positive and negative y will LOOK THE SAME.
10140 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10141 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10145 // the only tcmod that needs software vertex processing is turbulent, so
10146 // check for it here and apply the changes if needed
10147 // and we only support that as the first one
10148 // (handling a mixture of turbulent and other tcmods would be problematic
10149 // without punting it entirely to a software path)
10150 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10152 amplitude = rsurface.texture->tcmods[0].parms[1];
10153 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10154 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10155 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10156 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10157 for (j = 0;j < batchnumvertices;j++)
10159 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);
10160 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10164 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10166 // convert the modified arrays to vertex structs
10167 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10168 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10169 // rsurface.batchvertexmesh_bufferoffset = 0;
10170 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10171 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10172 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10173 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10174 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10175 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10176 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10178 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10180 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10181 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10184 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10185 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10186 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10187 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10188 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10189 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10190 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10191 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10192 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10193 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10195 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10197 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10198 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10203 // upload buffer data for the dynamic batch
10204 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10206 if (rsurface.batchvertexmesh)
10207 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10210 if (rsurface.batchvertex3f)
10211 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10212 if (rsurface.batchsvector3f)
10213 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10214 if (rsurface.batchtvector3f)
10215 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10216 if (rsurface.batchnormal3f)
10217 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10218 if (rsurface.batchlightmapcolor4f)
10219 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10220 if (rsurface.batchtexcoordtexture2f)
10221 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10222 if (rsurface.batchtexcoordlightmap2f)
10223 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10224 if (rsurface.batchskeletalindex4ub)
10225 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10226 if (rsurface.batchskeletalweight4ub)
10227 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10229 if (rsurface.batchelement3s)
10230 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10231 else if (rsurface.batchelement3i)
10232 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10236 void RSurf_DrawBatch(void)
10238 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10239 // through the pipeline, killing it earlier in the pipeline would have
10240 // per-surface overhead rather than per-batch overhead, so it's best to
10241 // reject it here, before it hits glDraw.
10242 if (rsurface.batchnumtriangles == 0)
10245 // batch debugging code
10246 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10252 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10253 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10256 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10258 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10260 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10261 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);
10268 if (rsurface.batchmultidraw)
10270 // issue multiple draws rather than copying index data
10271 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10272 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10273 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10274 for (i = 0;i < numsurfaces;)
10276 // combine consecutive surfaces as one draw
10277 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10278 if (surfacelist[j] != surfacelist[k] + 1)
10280 firstvertex = surfacelist[i]->num_firstvertex;
10281 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10282 firsttriangle = surfacelist[i]->num_firsttriangle;
10283 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10284 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);
10290 // there is only one consecutive run of index data (may have been combined)
10291 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);
10295 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10297 // pick the closest matching water plane
10298 int planeindex, vertexindex, bestplaneindex = -1;
10302 r_waterstate_waterplane_t *p;
10303 qboolean prepared = false;
10305 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10307 if(p->camera_entity != rsurface.texture->camera_entity)
10312 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10314 if(rsurface.batchnumvertices == 0)
10317 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10319 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10320 d += fabs(PlaneDiff(vert, &p->plane));
10322 if (bestd > d || bestplaneindex < 0)
10325 bestplaneindex = planeindex;
10328 return bestplaneindex;
10329 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10330 // this situation though, as it might be better to render single larger
10331 // batches with useless stuff (backface culled for example) than to
10332 // render multiple smaller batches
10335 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10338 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10339 rsurface.passcolor4f_vertexbuffer = 0;
10340 rsurface.passcolor4f_bufferoffset = 0;
10341 for (i = 0;i < rsurface.batchnumvertices;i++)
10342 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10345 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10352 if (rsurface.passcolor4f)
10354 // generate color arrays
10355 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10356 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10357 rsurface.passcolor4f_vertexbuffer = 0;
10358 rsurface.passcolor4f_bufferoffset = 0;
10359 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)
10361 f = RSurf_FogVertex(v);
10370 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10371 rsurface.passcolor4f_vertexbuffer = 0;
10372 rsurface.passcolor4f_bufferoffset = 0;
10373 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10375 f = RSurf_FogVertex(v);
10384 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10391 if (!rsurface.passcolor4f)
10393 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10394 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10395 rsurface.passcolor4f_vertexbuffer = 0;
10396 rsurface.passcolor4f_bufferoffset = 0;
10397 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)
10399 f = RSurf_FogVertex(v);
10400 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10401 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10402 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10407 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10412 if (!rsurface.passcolor4f)
10414 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10415 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10416 rsurface.passcolor4f_vertexbuffer = 0;
10417 rsurface.passcolor4f_bufferoffset = 0;
10418 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10427 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10432 if (!rsurface.passcolor4f)
10434 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10435 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10436 rsurface.passcolor4f_vertexbuffer = 0;
10437 rsurface.passcolor4f_bufferoffset = 0;
10438 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10440 c2[0] = c[0] + r_refdef.scene.ambient;
10441 c2[1] = c[1] + r_refdef.scene.ambient;
10442 c2[2] = c[2] + r_refdef.scene.ambient;
10447 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10450 rsurface.passcolor4f = NULL;
10451 rsurface.passcolor4f_vertexbuffer = 0;
10452 rsurface.passcolor4f_bufferoffset = 0;
10453 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10454 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10455 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10456 GL_Color(r, g, b, a);
10457 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10458 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10459 R_Mesh_TexMatrix(0, NULL);
10463 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10465 // TODO: optimize applyfog && applycolor case
10466 // just apply fog if necessary, and tint the fog color array if necessary
10467 rsurface.passcolor4f = NULL;
10468 rsurface.passcolor4f_vertexbuffer = 0;
10469 rsurface.passcolor4f_bufferoffset = 0;
10470 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10471 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10472 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10473 GL_Color(r, g, b, a);
10477 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10480 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10481 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10482 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10483 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10484 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10485 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10486 GL_Color(r, g, b, a);
10490 static void RSurf_DrawBatch_GL11_ClampColor(void)
10495 if (!rsurface.passcolor4f)
10497 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10499 c2[0] = bound(0.0f, c1[0], 1.0f);
10500 c2[1] = bound(0.0f, c1[1], 1.0f);
10501 c2[2] = bound(0.0f, c1[2], 1.0f);
10502 c2[3] = bound(0.0f, c1[3], 1.0f);
10506 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10516 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10517 rsurface.passcolor4f_vertexbuffer = 0;
10518 rsurface.passcolor4f_bufferoffset = 0;
10519 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)
10521 f = -DotProduct(r_refdef.view.forward, n);
10523 f = f * 0.85 + 0.15; // work around so stuff won't get black
10524 f *= r_refdef.lightmapintensity;
10525 Vector4Set(c, f, f, f, 1);
10529 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10531 RSurf_DrawBatch_GL11_ApplyFakeLight();
10532 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10533 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10534 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10535 GL_Color(r, g, b, a);
10539 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10547 vec3_t ambientcolor;
10548 vec3_t diffusecolor;
10552 VectorCopy(rsurface.modellight_lightdir, lightdir);
10553 f = 0.5f * r_refdef.lightmapintensity;
10554 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10555 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10556 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10557 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10558 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10559 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10561 if (VectorLength2(diffusecolor) > 0)
10563 // q3-style directional shading
10564 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10565 rsurface.passcolor4f_vertexbuffer = 0;
10566 rsurface.passcolor4f_bufferoffset = 0;
10567 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)
10569 if ((f = DotProduct(n, lightdir)) > 0)
10570 VectorMA(ambientcolor, f, diffusecolor, c);
10572 VectorCopy(ambientcolor, c);
10579 *applycolor = false;
10583 *r = ambientcolor[0];
10584 *g = ambientcolor[1];
10585 *b = ambientcolor[2];
10586 rsurface.passcolor4f = NULL;
10587 rsurface.passcolor4f_vertexbuffer = 0;
10588 rsurface.passcolor4f_bufferoffset = 0;
10592 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10594 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10595 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10596 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10597 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10598 GL_Color(r, g, b, a);
10602 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10610 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10611 rsurface.passcolor4f_vertexbuffer = 0;
10612 rsurface.passcolor4f_bufferoffset = 0;
10614 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10616 f = 1 - RSurf_FogVertex(v);
10624 void RSurf_SetupDepthAndCulling(void)
10626 // submodels are biased to avoid z-fighting with world surfaces that they
10627 // may be exactly overlapping (avoids z-fighting artifacts on certain
10628 // doors and things in Quake maps)
10629 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10630 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10631 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10632 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10635 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10637 // transparent sky would be ridiculous
10638 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10640 R_SetupShader_Generic_NoTexture(false, false);
10641 skyrenderlater = true;
10642 RSurf_SetupDepthAndCulling();
10643 GL_DepthMask(true);
10644 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10645 // skymasking on them, and Quake3 never did sky masking (unlike
10646 // software Quake and software Quake2), so disable the sky masking
10647 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10648 // and skymasking also looks very bad when noclipping outside the
10649 // level, so don't use it then either.
10650 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10652 R_Mesh_ResetTextureState();
10653 if (skyrendermasked)
10655 R_SetupShader_DepthOrShadow(false, false, false);
10656 // depth-only (masking)
10657 GL_ColorMask(0,0,0,0);
10658 // just to make sure that braindead drivers don't draw
10659 // anything despite that colormask...
10660 GL_BlendFunc(GL_ZERO, GL_ONE);
10661 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10662 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10666 R_SetupShader_Generic_NoTexture(false, false);
10668 GL_BlendFunc(GL_ONE, GL_ZERO);
10669 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10670 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10671 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10674 if (skyrendermasked)
10675 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10677 R_Mesh_ResetTextureState();
10678 GL_Color(1, 1, 1, 1);
10681 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10682 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10683 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10685 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10689 // render screenspace normalmap to texture
10690 GL_DepthMask(true);
10691 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10696 // bind lightmap texture
10698 // water/refraction/reflection/camera surfaces have to be handled specially
10699 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10701 int start, end, startplaneindex;
10702 for (start = 0;start < texturenumsurfaces;start = end)
10704 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10705 if(startplaneindex < 0)
10707 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10708 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10712 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10714 // now that we have a batch using the same planeindex, render it
10715 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10717 // render water or distortion background
10718 GL_DepthMask(true);
10719 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);
10721 // blend surface on top
10722 GL_DepthMask(false);
10723 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10726 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10728 // render surface with reflection texture as input
10729 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10730 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);
10737 // render surface batch normally
10738 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10739 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);
10743 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10745 // OpenGL 1.3 path - anything not completely ancient
10746 qboolean applycolor;
10749 const texturelayer_t *layer;
10750 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);
10751 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10753 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10756 int layertexrgbscale;
10757 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10759 if (layerindex == 0)
10760 GL_AlphaTest(true);
10763 GL_AlphaTest(false);
10764 GL_DepthFunc(GL_EQUAL);
10767 GL_DepthMask(layer->depthmask && writedepth);
10768 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10769 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10771 layertexrgbscale = 4;
10772 VectorScale(layer->color, 0.25f, layercolor);
10774 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10776 layertexrgbscale = 2;
10777 VectorScale(layer->color, 0.5f, layercolor);
10781 layertexrgbscale = 1;
10782 VectorScale(layer->color, 1.0f, layercolor);
10784 layercolor[3] = layer->color[3];
10785 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10786 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10787 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10788 switch (layer->type)
10790 case TEXTURELAYERTYPE_LITTEXTURE:
10791 // single-pass lightmapped texture with 2x rgbscale
10792 R_Mesh_TexBind(0, r_texture_white);
10793 R_Mesh_TexMatrix(0, NULL);
10794 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10795 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10796 R_Mesh_TexBind(1, layer->texture);
10797 R_Mesh_TexMatrix(1, &layer->texmatrix);
10798 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10799 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10800 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10801 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10802 else if (FAKELIGHT_ENABLED)
10803 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10804 else if (rsurface.uselightmaptexture)
10805 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10807 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10809 case TEXTURELAYERTYPE_TEXTURE:
10810 // singletexture unlit texture with transparency support
10811 R_Mesh_TexBind(0, layer->texture);
10812 R_Mesh_TexMatrix(0, &layer->texmatrix);
10813 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10814 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10815 R_Mesh_TexBind(1, 0);
10816 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10817 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10819 case TEXTURELAYERTYPE_FOG:
10820 // singletexture fogging
10821 if (layer->texture)
10823 R_Mesh_TexBind(0, layer->texture);
10824 R_Mesh_TexMatrix(0, &layer->texmatrix);
10825 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10826 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10830 R_Mesh_TexBind(0, 0);
10831 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10833 R_Mesh_TexBind(1, 0);
10834 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10835 // generate a color array for the fog pass
10836 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10837 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10841 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10844 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10846 GL_DepthFunc(GL_LEQUAL);
10847 GL_AlphaTest(false);
10851 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10853 // OpenGL 1.1 - crusty old voodoo path
10856 const texturelayer_t *layer;
10857 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);
10858 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10860 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10862 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10864 if (layerindex == 0)
10865 GL_AlphaTest(true);
10868 GL_AlphaTest(false);
10869 GL_DepthFunc(GL_EQUAL);
10872 GL_DepthMask(layer->depthmask && writedepth);
10873 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10874 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10875 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10876 switch (layer->type)
10878 case TEXTURELAYERTYPE_LITTEXTURE:
10879 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10881 // two-pass lit texture with 2x rgbscale
10882 // first the lightmap pass
10883 R_Mesh_TexBind(0, r_texture_white);
10884 R_Mesh_TexMatrix(0, NULL);
10885 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10886 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10887 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10888 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10889 else if (FAKELIGHT_ENABLED)
10890 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10891 else if (rsurface.uselightmaptexture)
10892 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10894 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10895 // then apply the texture to it
10896 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10897 R_Mesh_TexBind(0, layer->texture);
10898 R_Mesh_TexMatrix(0, &layer->texmatrix);
10899 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10900 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10901 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);
10905 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10906 R_Mesh_TexBind(0, layer->texture);
10907 R_Mesh_TexMatrix(0, &layer->texmatrix);
10908 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10909 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10910 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10911 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);
10912 else if (FAKELIGHT_ENABLED)
10913 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);
10915 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);
10918 case TEXTURELAYERTYPE_TEXTURE:
10919 // singletexture unlit texture with transparency support
10920 R_Mesh_TexBind(0, layer->texture);
10921 R_Mesh_TexMatrix(0, &layer->texmatrix);
10922 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10923 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10924 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);
10926 case TEXTURELAYERTYPE_FOG:
10927 // singletexture fogging
10928 if (layer->texture)
10930 R_Mesh_TexBind(0, layer->texture);
10931 R_Mesh_TexMatrix(0, &layer->texmatrix);
10932 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10933 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10937 R_Mesh_TexBind(0, 0);
10938 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10940 // generate a color array for the fog pass
10941 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10942 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10946 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10949 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10951 GL_DepthFunc(GL_LEQUAL);
10952 GL_AlphaTest(false);
10956 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10960 r_vertexgeneric_t *batchvertex;
10963 // R_Mesh_ResetTextureState();
10964 R_SetupShader_Generic_NoTexture(false, false);
10966 if(rsurface.texture && rsurface.texture->currentskinframe)
10968 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10969 c[3] *= rsurface.texture->currentalpha;
10979 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10981 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10982 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10983 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10986 // brighten it up (as texture value 127 means "unlit")
10987 c[0] *= 2 * r_refdef.view.colorscale;
10988 c[1] *= 2 * r_refdef.view.colorscale;
10989 c[2] *= 2 * r_refdef.view.colorscale;
10991 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10992 c[3] *= r_wateralpha.value;
10994 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10996 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10997 GL_DepthMask(false);
10999 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11001 GL_BlendFunc(GL_ONE, GL_ONE);
11002 GL_DepthMask(false);
11004 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11006 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11007 GL_DepthMask(false);
11009 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11011 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11012 GL_DepthMask(false);
11016 GL_BlendFunc(GL_ONE, GL_ZERO);
11017 GL_DepthMask(writedepth);
11020 if (r_showsurfaces.integer == 3)
11022 rsurface.passcolor4f = NULL;
11024 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11026 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11028 rsurface.passcolor4f = NULL;
11029 rsurface.passcolor4f_vertexbuffer = 0;
11030 rsurface.passcolor4f_bufferoffset = 0;
11032 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11034 qboolean applycolor = true;
11037 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11039 r_refdef.lightmapintensity = 1;
11040 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11041 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11043 else if (FAKELIGHT_ENABLED)
11045 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11047 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11048 RSurf_DrawBatch_GL11_ApplyFakeLight();
11049 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11053 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11055 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11056 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11057 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11060 if(!rsurface.passcolor4f)
11061 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11063 RSurf_DrawBatch_GL11_ApplyAmbient();
11064 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11065 if(r_refdef.fogenabled)
11066 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11067 RSurf_DrawBatch_GL11_ClampColor();
11069 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11070 R_SetupShader_Generic_NoTexture(false, false);
11073 else if (!r_refdef.view.showdebug)
11075 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11076 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11077 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11079 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11080 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11082 R_Mesh_PrepareVertices_Generic_Unlock();
11085 else if (r_showsurfaces.integer == 4)
11087 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11088 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11089 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11091 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11092 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11093 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11095 R_Mesh_PrepareVertices_Generic_Unlock();
11098 else if (r_showsurfaces.integer == 2)
11101 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11102 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11103 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11105 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11106 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11107 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11108 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11109 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11110 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11111 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11113 R_Mesh_PrepareVertices_Generic_Unlock();
11114 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11118 int texturesurfaceindex;
11120 const msurface_t *surface;
11121 float surfacecolor4f[4];
11122 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11123 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11125 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11127 surface = texturesurfacelist[texturesurfaceindex];
11128 k = (int)(((size_t)surface) / sizeof(msurface_t));
11129 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11130 for (j = 0;j < surface->num_vertices;j++)
11132 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11133 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11137 R_Mesh_PrepareVertices_Generic_Unlock();
11142 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11145 RSurf_SetupDepthAndCulling();
11146 if (r_showsurfaces.integer)
11148 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11151 switch (vid.renderpath)
11153 case RENDERPATH_GL20:
11154 case RENDERPATH_D3D9:
11155 case RENDERPATH_D3D10:
11156 case RENDERPATH_D3D11:
11157 case RENDERPATH_SOFT:
11158 case RENDERPATH_GLES2:
11159 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11161 case RENDERPATH_GL13:
11162 case RENDERPATH_GLES1:
11163 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11165 case RENDERPATH_GL11:
11166 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11172 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11175 RSurf_SetupDepthAndCulling();
11176 if (r_showsurfaces.integer)
11178 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11181 switch (vid.renderpath)
11183 case RENDERPATH_GL20:
11184 case RENDERPATH_D3D9:
11185 case RENDERPATH_D3D10:
11186 case RENDERPATH_D3D11:
11187 case RENDERPATH_SOFT:
11188 case RENDERPATH_GLES2:
11189 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11191 case RENDERPATH_GL13:
11192 case RENDERPATH_GLES1:
11193 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11195 case RENDERPATH_GL11:
11196 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11202 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11205 int texturenumsurfaces, endsurface;
11206 texture_t *texture;
11207 const msurface_t *surface;
11208 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11210 // if the model is static it doesn't matter what value we give for
11211 // wantnormals and wanttangents, so this logic uses only rules applicable
11212 // to a model, knowing that they are meaningless otherwise
11213 if (ent == r_refdef.scene.worldentity)
11214 RSurf_ActiveWorldEntity();
11215 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11216 RSurf_ActiveModelEntity(ent, false, false, false);
11219 switch (vid.renderpath)
11221 case RENDERPATH_GL20:
11222 case RENDERPATH_D3D9:
11223 case RENDERPATH_D3D10:
11224 case RENDERPATH_D3D11:
11225 case RENDERPATH_SOFT:
11226 case RENDERPATH_GLES2:
11227 RSurf_ActiveModelEntity(ent, true, true, false);
11229 case RENDERPATH_GL11:
11230 case RENDERPATH_GL13:
11231 case RENDERPATH_GLES1:
11232 RSurf_ActiveModelEntity(ent, true, false, false);
11237 if (r_transparentdepthmasking.integer)
11239 qboolean setup = false;
11240 for (i = 0;i < numsurfaces;i = j)
11243 surface = rsurface.modelsurfaces + surfacelist[i];
11244 texture = surface->texture;
11245 rsurface.texture = R_GetCurrentTexture(texture);
11246 rsurface.lightmaptexture = NULL;
11247 rsurface.deluxemaptexture = NULL;
11248 rsurface.uselightmaptexture = false;
11249 // scan ahead until we find a different texture
11250 endsurface = min(i + 1024, numsurfaces);
11251 texturenumsurfaces = 0;
11252 texturesurfacelist[texturenumsurfaces++] = surface;
11253 for (;j < endsurface;j++)
11255 surface = rsurface.modelsurfaces + surfacelist[j];
11256 if (texture != surface->texture)
11258 texturesurfacelist[texturenumsurfaces++] = surface;
11260 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11262 // render the range of surfaces as depth
11266 GL_ColorMask(0,0,0,0);
11268 GL_DepthTest(true);
11269 GL_BlendFunc(GL_ONE, GL_ZERO);
11270 GL_DepthMask(true);
11271 // R_Mesh_ResetTextureState();
11273 RSurf_SetupDepthAndCulling();
11274 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11275 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11276 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11280 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11283 for (i = 0;i < numsurfaces;i = j)
11286 surface = rsurface.modelsurfaces + surfacelist[i];
11287 texture = surface->texture;
11288 rsurface.texture = R_GetCurrentTexture(texture);
11289 // scan ahead until we find a different texture
11290 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11291 texturenumsurfaces = 0;
11292 texturesurfacelist[texturenumsurfaces++] = surface;
11293 if(FAKELIGHT_ENABLED)
11295 rsurface.lightmaptexture = NULL;
11296 rsurface.deluxemaptexture = NULL;
11297 rsurface.uselightmaptexture = false;
11298 for (;j < endsurface;j++)
11300 surface = rsurface.modelsurfaces + surfacelist[j];
11301 if (texture != surface->texture)
11303 texturesurfacelist[texturenumsurfaces++] = surface;
11308 rsurface.lightmaptexture = surface->lightmaptexture;
11309 rsurface.deluxemaptexture = surface->deluxemaptexture;
11310 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11311 for (;j < endsurface;j++)
11313 surface = rsurface.modelsurfaces + surfacelist[j];
11314 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11316 texturesurfacelist[texturenumsurfaces++] = surface;
11319 // render the range of surfaces
11320 if (ent == r_refdef.scene.worldentity)
11321 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11323 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11325 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11328 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11330 // transparent surfaces get pushed off into the transparent queue
11331 int surfacelistindex;
11332 const msurface_t *surface;
11333 vec3_t tempcenter, center;
11334 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11336 surface = texturesurfacelist[surfacelistindex];
11337 if (r_transparent_sortsurfacesbynearest.integer)
11339 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11340 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11341 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11345 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11346 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11347 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11349 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11350 if (rsurface.entity->transparent_offset) // transparent offset
11352 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11353 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11354 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11356 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);
11360 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11362 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11364 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11366 RSurf_SetupDepthAndCulling();
11367 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11368 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11369 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11373 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11377 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11380 if (!rsurface.texture->currentnumlayers)
11382 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11383 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11385 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11387 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11388 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11389 else if (!rsurface.texture->currentnumlayers)
11391 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11393 // in the deferred case, transparent surfaces were queued during prepass
11394 if (!r_shadow_usingdeferredprepass)
11395 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11399 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11400 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11405 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11408 texture_t *texture;
11409 R_FrameData_SetMark();
11410 // break the surface list down into batches by texture and use of lightmapping
11411 for (i = 0;i < numsurfaces;i = j)
11414 // texture is the base texture pointer, rsurface.texture is the
11415 // current frame/skin the texture is directing us to use (for example
11416 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11417 // use skin 1 instead)
11418 texture = surfacelist[i]->texture;
11419 rsurface.texture = R_GetCurrentTexture(texture);
11420 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11422 // if this texture is not the kind we want, skip ahead to the next one
11423 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11427 if(FAKELIGHT_ENABLED || depthonly || prepass)
11429 rsurface.lightmaptexture = NULL;
11430 rsurface.deluxemaptexture = NULL;
11431 rsurface.uselightmaptexture = false;
11432 // simply scan ahead until we find a different texture or lightmap state
11433 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11438 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11439 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11440 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11441 // simply scan ahead until we find a different texture or lightmap state
11442 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11445 // render the range of surfaces
11446 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11448 R_FrameData_ReturnToMark();
11451 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11455 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11458 if (!rsurface.texture->currentnumlayers)
11460 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11461 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11463 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11465 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11466 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11467 else if (!rsurface.texture->currentnumlayers)
11469 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11471 // in the deferred case, transparent surfaces were queued during prepass
11472 if (!r_shadow_usingdeferredprepass)
11473 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11477 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11478 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11483 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11486 texture_t *texture;
11487 R_FrameData_SetMark();
11488 // break the surface list down into batches by texture and use of lightmapping
11489 for (i = 0;i < numsurfaces;i = j)
11492 // texture is the base texture pointer, rsurface.texture is the
11493 // current frame/skin the texture is directing us to use (for example
11494 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11495 // use skin 1 instead)
11496 texture = surfacelist[i]->texture;
11497 rsurface.texture = R_GetCurrentTexture(texture);
11498 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11500 // if this texture is not the kind we want, skip ahead to the next one
11501 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11505 if(FAKELIGHT_ENABLED || depthonly || prepass)
11507 rsurface.lightmaptexture = NULL;
11508 rsurface.deluxemaptexture = NULL;
11509 rsurface.uselightmaptexture = false;
11510 // simply scan ahead until we find a different texture or lightmap state
11511 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11516 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11517 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11518 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11519 // simply scan ahead until we find a different texture or lightmap state
11520 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11523 // render the range of surfaces
11524 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11526 R_FrameData_ReturnToMark();
11529 float locboxvertex3f[6*4*3] =
11531 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11532 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11533 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11534 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11535 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11536 1,0,0, 0,0,0, 0,1,0, 1,1,0
11539 unsigned short locboxelements[6*2*3] =
11544 12,13,14, 12,14,15,
11545 16,17,18, 16,18,19,
11549 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11552 cl_locnode_t *loc = (cl_locnode_t *)ent;
11554 float vertex3f[6*4*3];
11556 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11557 GL_DepthMask(false);
11558 GL_DepthRange(0, 1);
11559 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11560 GL_DepthTest(true);
11561 GL_CullFace(GL_NONE);
11562 R_EntityMatrix(&identitymatrix);
11564 // R_Mesh_ResetTextureState();
11566 i = surfacelist[0];
11567 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11568 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11569 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11570 surfacelist[0] < 0 ? 0.5f : 0.125f);
11572 if (VectorCompare(loc->mins, loc->maxs))
11574 VectorSet(size, 2, 2, 2);
11575 VectorMA(loc->mins, -0.5f, size, mins);
11579 VectorCopy(loc->mins, mins);
11580 VectorSubtract(loc->maxs, loc->mins, size);
11583 for (i = 0;i < 6*4*3;)
11584 for (j = 0;j < 3;j++, i++)
11585 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11587 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11588 R_SetupShader_Generic_NoTexture(false, false);
11589 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11592 void R_DrawLocs(void)
11595 cl_locnode_t *loc, *nearestloc;
11597 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11598 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11600 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11601 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11605 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11607 if (decalsystem->decals)
11608 Mem_Free(decalsystem->decals);
11609 memset(decalsystem, 0, sizeof(*decalsystem));
11612 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)
11615 tridecal_t *decals;
11618 // expand or initialize the system
11619 if (decalsystem->maxdecals <= decalsystem->numdecals)
11621 decalsystem_t old = *decalsystem;
11622 qboolean useshortelements;
11623 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11624 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11625 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)));
11626 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11627 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11628 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11629 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11630 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11631 if (decalsystem->numdecals)
11632 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11634 Mem_Free(old.decals);
11635 for (i = 0;i < decalsystem->maxdecals*3;i++)
11636 decalsystem->element3i[i] = i;
11637 if (useshortelements)
11638 for (i = 0;i < decalsystem->maxdecals*3;i++)
11639 decalsystem->element3s[i] = i;
11642 // grab a decal and search for another free slot for the next one
11643 decals = decalsystem->decals;
11644 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11645 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11647 decalsystem->freedecal = i;
11648 if (decalsystem->numdecals <= i)
11649 decalsystem->numdecals = i + 1;
11651 // initialize the decal
11653 decal->triangleindex = triangleindex;
11654 decal->surfaceindex = surfaceindex;
11655 decal->decalsequence = decalsequence;
11656 decal->color4f[0][0] = c0[0];
11657 decal->color4f[0][1] = c0[1];
11658 decal->color4f[0][2] = c0[2];
11659 decal->color4f[0][3] = 1;
11660 decal->color4f[1][0] = c1[0];
11661 decal->color4f[1][1] = c1[1];
11662 decal->color4f[1][2] = c1[2];
11663 decal->color4f[1][3] = 1;
11664 decal->color4f[2][0] = c2[0];
11665 decal->color4f[2][1] = c2[1];
11666 decal->color4f[2][2] = c2[2];
11667 decal->color4f[2][3] = 1;
11668 decal->vertex3f[0][0] = v0[0];
11669 decal->vertex3f[0][1] = v0[1];
11670 decal->vertex3f[0][2] = v0[2];
11671 decal->vertex3f[1][0] = v1[0];
11672 decal->vertex3f[1][1] = v1[1];
11673 decal->vertex3f[1][2] = v1[2];
11674 decal->vertex3f[2][0] = v2[0];
11675 decal->vertex3f[2][1] = v2[1];
11676 decal->vertex3f[2][2] = v2[2];
11677 decal->texcoord2f[0][0] = t0[0];
11678 decal->texcoord2f[0][1] = t0[1];
11679 decal->texcoord2f[1][0] = t1[0];
11680 decal->texcoord2f[1][1] = t1[1];
11681 decal->texcoord2f[2][0] = t2[0];
11682 decal->texcoord2f[2][1] = t2[1];
11683 TriangleNormal(v0, v1, v2, decal->plane);
11684 VectorNormalize(decal->plane);
11685 decal->plane[3] = DotProduct(v0, decal->plane);
11688 extern cvar_t cl_decals_bias;
11689 extern cvar_t cl_decals_models;
11690 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11691 // baseparms, parms, temps
11692 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)
11697 const float *vertex3f;
11698 const float *normal3f;
11700 float points[2][9][3];
11707 e = rsurface.modelelement3i + 3*triangleindex;
11709 vertex3f = rsurface.modelvertex3f;
11710 normal3f = rsurface.modelnormal3f;
11714 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11716 index = 3*e[cornerindex];
11717 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11722 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11724 index = 3*e[cornerindex];
11725 VectorCopy(vertex3f + index, v[cornerindex]);
11730 //TriangleNormal(v[0], v[1], v[2], normal);
11731 //if (DotProduct(normal, localnormal) < 0.0f)
11733 // clip by each of the box planes formed from the projection matrix
11734 // if anything survives, we emit the decal
11735 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]);
11738 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]);
11741 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]);
11744 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]);
11747 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]);
11750 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]);
11753 // some part of the triangle survived, so we have to accept it...
11756 // dynamic always uses the original triangle
11758 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11760 index = 3*e[cornerindex];
11761 VectorCopy(vertex3f + index, v[cornerindex]);
11764 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11766 // convert vertex positions to texcoords
11767 Matrix4x4_Transform(projection, v[cornerindex], temp);
11768 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11769 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11770 // calculate distance fade from the projection origin
11771 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11772 f = bound(0.0f, f, 1.0f);
11773 c[cornerindex][0] = r * f;
11774 c[cornerindex][1] = g * f;
11775 c[cornerindex][2] = b * f;
11776 c[cornerindex][3] = 1.0f;
11777 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11780 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);
11782 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11783 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);
11785 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)
11787 matrix4x4_t projection;
11788 decalsystem_t *decalsystem;
11791 const msurface_t *surface;
11792 const msurface_t *surfaces;
11793 const int *surfacelist;
11794 const texture_t *texture;
11796 int numsurfacelist;
11797 int surfacelistindex;
11800 float localorigin[3];
11801 float localnormal[3];
11802 float localmins[3];
11803 float localmaxs[3];
11806 float planes[6][4];
11809 int bih_triangles_count;
11810 int bih_triangles[256];
11811 int bih_surfaces[256];
11813 decalsystem = &ent->decalsystem;
11814 model = ent->model;
11815 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11817 R_DecalSystem_Reset(&ent->decalsystem);
11821 if (!model->brush.data_leafs && !cl_decals_models.integer)
11823 if (decalsystem->model)
11824 R_DecalSystem_Reset(decalsystem);
11828 if (decalsystem->model != model)
11829 R_DecalSystem_Reset(decalsystem);
11830 decalsystem->model = model;
11832 RSurf_ActiveModelEntity(ent, true, false, false);
11834 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11835 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11836 VectorNormalize(localnormal);
11837 localsize = worldsize*rsurface.inversematrixscale;
11838 localmins[0] = localorigin[0] - localsize;
11839 localmins[1] = localorigin[1] - localsize;
11840 localmins[2] = localorigin[2] - localsize;
11841 localmaxs[0] = localorigin[0] + localsize;
11842 localmaxs[1] = localorigin[1] + localsize;
11843 localmaxs[2] = localorigin[2] + localsize;
11845 //VectorCopy(localnormal, planes[4]);
11846 //VectorVectors(planes[4], planes[2], planes[0]);
11847 AnglesFromVectors(angles, localnormal, NULL, false);
11848 AngleVectors(angles, planes[0], planes[2], planes[4]);
11849 VectorNegate(planes[0], planes[1]);
11850 VectorNegate(planes[2], planes[3]);
11851 VectorNegate(planes[4], planes[5]);
11852 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11853 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11854 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11855 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11856 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11857 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11862 matrix4x4_t forwardprojection;
11863 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11864 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11869 float projectionvector[4][3];
11870 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11871 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11872 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11873 projectionvector[0][0] = planes[0][0] * ilocalsize;
11874 projectionvector[0][1] = planes[1][0] * ilocalsize;
11875 projectionvector[0][2] = planes[2][0] * ilocalsize;
11876 projectionvector[1][0] = planes[0][1] * ilocalsize;
11877 projectionvector[1][1] = planes[1][1] * ilocalsize;
11878 projectionvector[1][2] = planes[2][1] * ilocalsize;
11879 projectionvector[2][0] = planes[0][2] * ilocalsize;
11880 projectionvector[2][1] = planes[1][2] * ilocalsize;
11881 projectionvector[2][2] = planes[2][2] * ilocalsize;
11882 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11883 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11884 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11885 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11889 dynamic = model->surfmesh.isanimated;
11890 numsurfacelist = model->nummodelsurfaces;
11891 surfacelist = model->sortedmodelsurfaces;
11892 surfaces = model->data_surfaces;
11895 bih_triangles_count = -1;
11898 if(model->render_bih.numleafs)
11899 bih = &model->render_bih;
11900 else if(model->collision_bih.numleafs)
11901 bih = &model->collision_bih;
11904 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11905 if(bih_triangles_count == 0)
11907 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11909 if(bih_triangles_count > 0)
11911 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11913 surfaceindex = bih_surfaces[triangleindex];
11914 surface = surfaces + surfaceindex;
11915 texture = surface->texture;
11916 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11918 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11920 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11925 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11927 surfaceindex = surfacelist[surfacelistindex];
11928 surface = surfaces + surfaceindex;
11929 // check cull box first because it rejects more than any other check
11930 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11932 // skip transparent surfaces
11933 texture = surface->texture;
11934 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11936 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11938 numtriangles = surface->num_triangles;
11939 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11940 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11945 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11946 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)
11948 int renderentityindex;
11949 float worldmins[3];
11950 float worldmaxs[3];
11951 entity_render_t *ent;
11953 if (!cl_decals_newsystem.integer)
11956 worldmins[0] = worldorigin[0] - worldsize;
11957 worldmins[1] = worldorigin[1] - worldsize;
11958 worldmins[2] = worldorigin[2] - worldsize;
11959 worldmaxs[0] = worldorigin[0] + worldsize;
11960 worldmaxs[1] = worldorigin[1] + worldsize;
11961 worldmaxs[2] = worldorigin[2] + worldsize;
11963 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11965 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11967 ent = r_refdef.scene.entities[renderentityindex];
11968 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11971 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11975 typedef struct r_decalsystem_splatqueue_s
11977 vec3_t worldorigin;
11978 vec3_t worldnormal;
11984 r_decalsystem_splatqueue_t;
11986 int r_decalsystem_numqueued = 0;
11987 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11989 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)
11991 r_decalsystem_splatqueue_t *queue;
11993 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11996 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11997 VectorCopy(worldorigin, queue->worldorigin);
11998 VectorCopy(worldnormal, queue->worldnormal);
11999 Vector4Set(queue->color, r, g, b, a);
12000 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12001 queue->worldsize = worldsize;
12002 queue->decalsequence = cl.decalsequence++;
12005 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12008 r_decalsystem_splatqueue_t *queue;
12010 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12011 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);
12012 r_decalsystem_numqueued = 0;
12015 extern cvar_t cl_decals_max;
12016 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12019 decalsystem_t *decalsystem = &ent->decalsystem;
12026 if (!decalsystem->numdecals)
12029 if (r_showsurfaces.integer)
12032 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12034 R_DecalSystem_Reset(decalsystem);
12038 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12039 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12041 if (decalsystem->lastupdatetime)
12042 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12045 decalsystem->lastupdatetime = r_refdef.scene.time;
12046 numdecals = decalsystem->numdecals;
12048 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12050 if (decal->color4f[0][3])
12052 decal->lived += frametime;
12053 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12055 memset(decal, 0, sizeof(*decal));
12056 if (decalsystem->freedecal > i)
12057 decalsystem->freedecal = i;
12061 decal = decalsystem->decals;
12062 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12065 // collapse the array by shuffling the tail decals into the gaps
12068 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12069 decalsystem->freedecal++;
12070 if (decalsystem->freedecal == numdecals)
12072 decal[decalsystem->freedecal] = decal[--numdecals];
12075 decalsystem->numdecals = numdecals;
12077 if (numdecals <= 0)
12079 // if there are no decals left, reset decalsystem
12080 R_DecalSystem_Reset(decalsystem);
12084 extern skinframe_t *decalskinframe;
12085 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12088 decalsystem_t *decalsystem = &ent->decalsystem;
12097 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12100 numdecals = decalsystem->numdecals;
12104 if (r_showsurfaces.integer)
12107 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12109 R_DecalSystem_Reset(decalsystem);
12113 // if the model is static it doesn't matter what value we give for
12114 // wantnormals and wanttangents, so this logic uses only rules applicable
12115 // to a model, knowing that they are meaningless otherwise
12116 if (ent == r_refdef.scene.worldentity)
12117 RSurf_ActiveWorldEntity();
12119 RSurf_ActiveModelEntity(ent, false, false, false);
12121 decalsystem->lastupdatetime = r_refdef.scene.time;
12123 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12125 // update vertex positions for animated models
12126 v3f = decalsystem->vertex3f;
12127 c4f = decalsystem->color4f;
12128 t2f = decalsystem->texcoord2f;
12129 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12131 if (!decal->color4f[0][3])
12134 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12138 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12141 // update color values for fading decals
12142 if (decal->lived >= cl_decals_time.value)
12143 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12147 c4f[ 0] = decal->color4f[0][0] * alpha;
12148 c4f[ 1] = decal->color4f[0][1] * alpha;
12149 c4f[ 2] = decal->color4f[0][2] * alpha;
12151 c4f[ 4] = decal->color4f[1][0] * alpha;
12152 c4f[ 5] = decal->color4f[1][1] * alpha;
12153 c4f[ 6] = decal->color4f[1][2] * alpha;
12155 c4f[ 8] = decal->color4f[2][0] * alpha;
12156 c4f[ 9] = decal->color4f[2][1] * alpha;
12157 c4f[10] = decal->color4f[2][2] * alpha;
12160 t2f[0] = decal->texcoord2f[0][0];
12161 t2f[1] = decal->texcoord2f[0][1];
12162 t2f[2] = decal->texcoord2f[1][0];
12163 t2f[3] = decal->texcoord2f[1][1];
12164 t2f[4] = decal->texcoord2f[2][0];
12165 t2f[5] = decal->texcoord2f[2][1];
12167 // update vertex positions for animated models
12168 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12170 e = rsurface.modelelement3i + 3*decal->triangleindex;
12171 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12172 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12173 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12177 VectorCopy(decal->vertex3f[0], v3f);
12178 VectorCopy(decal->vertex3f[1], v3f + 3);
12179 VectorCopy(decal->vertex3f[2], v3f + 6);
12182 if (r_refdef.fogenabled)
12184 alpha = RSurf_FogVertex(v3f);
12185 VectorScale(c4f, alpha, c4f);
12186 alpha = RSurf_FogVertex(v3f + 3);
12187 VectorScale(c4f + 4, alpha, c4f + 4);
12188 alpha = RSurf_FogVertex(v3f + 6);
12189 VectorScale(c4f + 8, alpha, c4f + 8);
12200 r_refdef.stats[r_stat_drawndecals] += numtris;
12202 // now render the decals all at once
12203 // (this assumes they all use one particle font texture!)
12204 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);
12205 // R_Mesh_ResetTextureState();
12206 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12207 GL_DepthMask(false);
12208 GL_DepthRange(0, 1);
12209 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12210 GL_DepthTest(true);
12211 GL_CullFace(GL_NONE);
12212 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12213 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12214 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12218 static void R_DrawModelDecals(void)
12222 // fade faster when there are too many decals
12223 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12224 for (i = 0;i < r_refdef.scene.numentities;i++)
12225 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12227 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12228 for (i = 0;i < r_refdef.scene.numentities;i++)
12229 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12230 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12232 R_DecalSystem_ApplySplatEntitiesQueue();
12234 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12235 for (i = 0;i < r_refdef.scene.numentities;i++)
12236 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12238 r_refdef.stats[r_stat_totaldecals] += numdecals;
12240 if (r_showsurfaces.integer)
12243 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12245 for (i = 0;i < r_refdef.scene.numentities;i++)
12247 if (!r_refdef.viewcache.entityvisible[i])
12249 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12250 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12254 extern cvar_t mod_collision_bih;
12255 static void R_DrawDebugModel(void)
12257 entity_render_t *ent = rsurface.entity;
12258 int i, j, flagsmask;
12259 const msurface_t *surface;
12260 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)
12394 if (r_showdisabledepthtest.integer)
12396 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12397 GL_DepthMask(false);
12401 GL_BlendFunc(GL_ONE, GL_ZERO);
12402 GL_DepthMask(true);
12404 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12406 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12408 rsurface.texture = R_GetCurrentTexture(surface->texture);
12409 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12411 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12412 qglBegin(GL_LINES);
12413 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12415 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12417 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12418 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12419 qglVertex3f(v[0], v[1], v[2]);
12420 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12421 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12422 qglVertex3f(v[0], v[1], v[2]);
12425 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12427 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12429 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12430 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12431 qglVertex3f(v[0], v[1], v[2]);
12432 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12433 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12434 qglVertex3f(v[0], v[1], v[2]);
12437 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12439 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12441 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12442 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12443 qglVertex3f(v[0], v[1], v[2]);
12444 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12445 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12446 qglVertex3f(v[0], v[1], v[2]);
12449 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12451 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12453 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12454 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12455 qglVertex3f(v[0], v[1], v[2]);
12456 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12457 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12458 qglVertex3f(v[0], v[1], v[2]);
12465 rsurface.texture = NULL;
12470 int r_maxsurfacelist = 0;
12471 const msurface_t **r_surfacelist = NULL;
12472 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12474 int i, j, endj, flagsmask;
12475 dp_model_t *model = r_refdef.scene.worldmodel;
12476 msurface_t *surfaces;
12477 unsigned char *update;
12478 int numsurfacelist = 0;
12482 if (r_maxsurfacelist < model->num_surfaces)
12484 r_maxsurfacelist = model->num_surfaces;
12486 Mem_Free((msurface_t**)r_surfacelist);
12487 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12490 RSurf_ActiveWorldEntity();
12492 surfaces = model->data_surfaces;
12493 update = model->brushq1.lightmapupdateflags;
12495 // update light styles on this submodel
12496 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12498 model_brush_lightstyleinfo_t *style;
12499 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12501 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12503 int *list = style->surfacelist;
12504 style->value = r_refdef.scene.lightstylevalue[style->style];
12505 for (j = 0;j < style->numsurfaces;j++)
12506 update[list[j]] = true;
12511 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12515 R_DrawDebugModel();
12516 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12520 rsurface.lightmaptexture = NULL;
12521 rsurface.deluxemaptexture = NULL;
12522 rsurface.uselightmaptexture = false;
12523 rsurface.texture = NULL;
12524 rsurface.rtlight = NULL;
12525 numsurfacelist = 0;
12526 // add visible surfaces to draw list
12527 for (i = 0;i < model->nummodelsurfaces;i++)
12529 j = model->sortedmodelsurfaces[i];
12530 if (r_refdef.viewcache.world_surfacevisible[j])
12531 r_surfacelist[numsurfacelist++] = surfaces + j;
12533 // update lightmaps if needed
12534 if (model->brushq1.firstrender)
12536 model->brushq1.firstrender = false;
12537 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12539 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12543 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12544 if (r_refdef.viewcache.world_surfacevisible[j])
12546 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12548 // don't do anything if there were no surfaces
12549 if (!numsurfacelist)
12551 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12554 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12556 // add to stats if desired
12557 if (r_speeds.integer && !skysurfaces && !depthonly)
12559 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12560 for (j = 0;j < numsurfacelist;j++)
12561 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12564 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12567 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12569 int i, j, endj, flagsmask;
12570 dp_model_t *model = ent->model;
12571 msurface_t *surfaces;
12572 unsigned char *update;
12573 int numsurfacelist = 0;
12577 if (r_maxsurfacelist < model->num_surfaces)
12579 r_maxsurfacelist = model->num_surfaces;
12581 Mem_Free((msurface_t **)r_surfacelist);
12582 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12585 // if the model is static it doesn't matter what value we give for
12586 // wantnormals and wanttangents, so this logic uses only rules applicable
12587 // to a model, knowing that they are meaningless otherwise
12588 if (ent == r_refdef.scene.worldentity)
12589 RSurf_ActiveWorldEntity();
12590 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12591 RSurf_ActiveModelEntity(ent, false, false, false);
12593 RSurf_ActiveModelEntity(ent, true, true, true);
12594 else if (depthonly)
12596 switch (vid.renderpath)
12598 case RENDERPATH_GL20:
12599 case RENDERPATH_D3D9:
12600 case RENDERPATH_D3D10:
12601 case RENDERPATH_D3D11:
12602 case RENDERPATH_SOFT:
12603 case RENDERPATH_GLES2:
12604 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12606 case RENDERPATH_GL11:
12607 case RENDERPATH_GL13:
12608 case RENDERPATH_GLES1:
12609 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12615 switch (vid.renderpath)
12617 case RENDERPATH_GL20:
12618 case RENDERPATH_D3D9:
12619 case RENDERPATH_D3D10:
12620 case RENDERPATH_D3D11:
12621 case RENDERPATH_SOFT:
12622 case RENDERPATH_GLES2:
12623 RSurf_ActiveModelEntity(ent, true, true, false);
12625 case RENDERPATH_GL11:
12626 case RENDERPATH_GL13:
12627 case RENDERPATH_GLES1:
12628 RSurf_ActiveModelEntity(ent, true, false, false);
12633 surfaces = model->data_surfaces;
12634 update = model->brushq1.lightmapupdateflags;
12636 // update light styles
12637 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12639 model_brush_lightstyleinfo_t *style;
12640 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12642 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12644 int *list = style->surfacelist;
12645 style->value = r_refdef.scene.lightstylevalue[style->style];
12646 for (j = 0;j < style->numsurfaces;j++)
12647 update[list[j]] = true;
12652 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12656 R_DrawDebugModel();
12657 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12661 rsurface.lightmaptexture = NULL;
12662 rsurface.deluxemaptexture = NULL;
12663 rsurface.uselightmaptexture = false;
12664 rsurface.texture = NULL;
12665 rsurface.rtlight = NULL;
12666 numsurfacelist = 0;
12667 // add visible surfaces to draw list
12668 for (i = 0;i < model->nummodelsurfaces;i++)
12669 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12670 // don't do anything if there were no surfaces
12671 if (!numsurfacelist)
12673 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12676 // update lightmaps if needed
12680 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12685 R_BuildLightMap(ent, surfaces + j);
12690 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12692 // add to stats if desired
12693 if (r_speeds.integer && !skysurfaces && !depthonly)
12695 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12696 for (j = 0;j < numsurfacelist;j++)
12697 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12700 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12703 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12705 static texture_t texture;
12706 static msurface_t surface;
12707 const msurface_t *surfacelist = &surface;
12709 // fake enough texture and surface state to render this geometry
12711 texture.update_lastrenderframe = -1; // regenerate this texture
12712 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12713 texture.currentskinframe = skinframe;
12714 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12715 texture.offsetmapping = OFFSETMAPPING_OFF;
12716 texture.offsetscale = 1;
12717 texture.specularscalemod = 1;
12718 texture.specularpowermod = 1;
12719 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12720 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12721 // JUST GREP FOR "specularscalemod = 1".
12723 surface.texture = &texture;
12724 surface.num_triangles = numtriangles;
12725 surface.num_firsttriangle = firsttriangle;
12726 surface.num_vertices = numvertices;
12727 surface.num_firstvertex = firstvertex;
12730 rsurface.texture = R_GetCurrentTexture(surface.texture);
12731 rsurface.lightmaptexture = NULL;
12732 rsurface.deluxemaptexture = NULL;
12733 rsurface.uselightmaptexture = false;
12734 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12737 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)
12739 static msurface_t surface;
12740 const msurface_t *surfacelist = &surface;
12742 // fake enough texture and surface state to render this geometry
12743 surface.texture = texture;
12744 surface.num_triangles = numtriangles;
12745 surface.num_firsttriangle = firsttriangle;
12746 surface.num_vertices = numvertices;
12747 surface.num_firstvertex = firstvertex;
12750 rsurface.texture = R_GetCurrentTexture(surface.texture);
12751 rsurface.lightmaptexture = NULL;
12752 rsurface.deluxemaptexture = NULL;
12753 rsurface.uselightmaptexture = false;
12754 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);