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
4473 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4475 // clear to black (loading plaque will be seen over this)
4476 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4480 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4484 if (r_trippy.integer)
4486 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4488 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4491 p = r_refdef.view.frustum + i;
4496 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4500 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4504 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4508 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4512 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4516 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4520 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4524 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4532 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4536 if (r_trippy.integer)
4538 for (i = 0;i < numplanes;i++)
4545 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4549 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4553 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4557 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4561 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4565 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4569 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4573 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4581 //==================================================================================
4583 // LordHavoc: this stores temporary data used within the same frame
4585 typedef struct r_framedata_mem_s
4587 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4588 size_t size; // how much usable space
4589 size_t current; // how much space in use
4590 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4591 size_t wantedsize; // how much space was allocated
4592 unsigned char *data; // start of real data (16byte aligned)
4596 static r_framedata_mem_t *r_framedata_mem;
4598 void R_FrameData_Reset(void)
4600 while (r_framedata_mem)
4602 r_framedata_mem_t *next = r_framedata_mem->purge;
4603 Mem_Free(r_framedata_mem);
4604 r_framedata_mem = next;
4608 static void R_FrameData_Resize(qboolean mustgrow)
4611 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4612 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4613 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4615 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4616 newmem->wantedsize = wantedsize;
4617 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4618 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4619 newmem->current = 0;
4621 newmem->purge = r_framedata_mem;
4622 r_framedata_mem = newmem;
4626 void R_FrameData_NewFrame(void)
4628 R_FrameData_Resize(false);
4629 if (!r_framedata_mem)
4631 // if we ran out of space on the last frame, free the old memory now
4632 while (r_framedata_mem->purge)
4634 // repeatedly remove the second item in the list, leaving only head
4635 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4636 Mem_Free(r_framedata_mem->purge);
4637 r_framedata_mem->purge = next;
4639 // reset the current mem pointer
4640 r_framedata_mem->current = 0;
4641 r_framedata_mem->mark = 0;
4644 void *R_FrameData_Alloc(size_t size)
4649 // align to 16 byte boundary - the data pointer is already aligned, so we
4650 // only need to ensure the size of every allocation is also aligned
4651 size = (size + 15) & ~15;
4653 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4655 // emergency - we ran out of space, allocate more memory
4656 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4657 // this might not be a growing it, but we'll allocate another buffer every time
4658 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4659 R_FrameData_Resize(true);
4662 data = r_framedata_mem->data + r_framedata_mem->current;
4663 r_framedata_mem->current += size;
4665 // count the usage for stats
4666 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4667 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4669 return (void *)data;
4672 void *R_FrameData_Store(size_t size, void *data)
4674 void *d = R_FrameData_Alloc(size);
4676 memcpy(d, data, size);
4680 void R_FrameData_SetMark(void)
4682 if (!r_framedata_mem)
4684 r_framedata_mem->mark = r_framedata_mem->current;
4687 void R_FrameData_ReturnToMark(void)
4689 if (!r_framedata_mem)
4691 r_framedata_mem->current = r_framedata_mem->mark;
4694 //==================================================================================
4696 // avoid reusing the same buffer objects on consecutive frames
4697 #define R_BUFFERDATA_CYCLE 3
4699 typedef struct r_bufferdata_buffer_s
4701 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4702 size_t size; // how much usable space
4703 size_t current; // how much space in use
4704 r_meshbuffer_t *buffer; // the buffer itself
4706 r_bufferdata_buffer_t;
4708 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4709 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4711 /// frees all dynamic buffers
4712 void R_BufferData_Reset(void)
4715 r_bufferdata_buffer_t **p, *mem;
4716 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4718 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4721 p = &r_bufferdata_buffer[cycle][type];
4727 R_Mesh_DestroyMeshBuffer(mem->buffer);
4734 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4735 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4737 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4739 float newvalue = r_buffermegs[type].value;
4741 // increase the cvar if we have to (but only if we already have a mem)
4742 if (mustgrow && mem)
4744 newvalue = bound(0.25f, newvalue, 256.0f);
4745 while (newvalue * 1024*1024 < minsize)
4748 // clamp the cvar to valid range
4749 newvalue = bound(0.25f, newvalue, 256.0f);
4750 if (r_buffermegs[type].value != newvalue)
4751 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4753 // calculate size in bytes
4754 size = (size_t)(newvalue * 1024*1024);
4755 size = bound(131072, size, 256*1024*1024);
4757 // allocate a new buffer if the size is different (purge old one later)
4758 // or if we were told we must grow the buffer
4759 if (!mem || mem->size != size || mustgrow)
4761 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4764 if (type == R_BUFFERDATA_VERTEX)
4765 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4766 else if (type == R_BUFFERDATA_INDEX16)
4767 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4768 else if (type == R_BUFFERDATA_INDEX32)
4769 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4770 else if (type == R_BUFFERDATA_UNIFORM)
4771 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4772 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4773 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4777 void R_BufferData_NewFrame(void)
4780 r_bufferdata_buffer_t **p, *mem;
4781 // cycle to the next frame's buffers
4782 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4783 // if we ran out of space on the last time we used these buffers, free the old memory now
4784 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4786 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4788 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4789 // free all but the head buffer, this is how we recycle obsolete
4790 // buffers after they are no longer in use
4791 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4797 R_Mesh_DestroyMeshBuffer(mem->buffer);
4800 // reset the current offset
4801 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4806 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4808 r_bufferdata_buffer_t *mem;
4812 *returnbufferoffset = 0;
4814 // align size to a byte boundary appropriate for the buffer type, this
4815 // makes all allocations have aligned start offsets
4816 if (type == R_BUFFERDATA_UNIFORM)
4817 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4819 padsize = (datasize + 15) & ~15;
4821 // if we ran out of space in this buffer we must allocate a new one
4822 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)
4823 R_BufferData_Resize(type, true, padsize);
4825 // if the resize did not give us enough memory, fail
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 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4829 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4830 offset = mem->current;
4831 mem->current += padsize;
4833 // upload the data to the buffer at the chosen offset
4835 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4836 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4838 // count the usage for stats
4839 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4840 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4842 // return the buffer offset
4843 *returnbufferoffset = offset;
4848 //==================================================================================
4850 // LordHavoc: animcache originally written by Echon, rewritten since then
4853 * Animation cache prevents re-generating mesh data for an animated model
4854 * multiple times in one frame for lighting, shadowing, reflections, etc.
4857 void R_AnimCache_Free(void)
4861 void R_AnimCache_ClearCache(void)
4864 entity_render_t *ent;
4866 for (i = 0;i < r_refdef.scene.numentities;i++)
4868 ent = r_refdef.scene.entities[i];
4869 ent->animcache_vertex3f = NULL;
4870 ent->animcache_vertex3f_vertexbuffer = NULL;
4871 ent->animcache_vertex3f_bufferoffset = 0;
4872 ent->animcache_normal3f = NULL;
4873 ent->animcache_normal3f_vertexbuffer = NULL;
4874 ent->animcache_normal3f_bufferoffset = 0;
4875 ent->animcache_svector3f = NULL;
4876 ent->animcache_svector3f_vertexbuffer = NULL;
4877 ent->animcache_svector3f_bufferoffset = 0;
4878 ent->animcache_tvector3f = NULL;
4879 ent->animcache_tvector3f_vertexbuffer = NULL;
4880 ent->animcache_tvector3f_bufferoffset = 0;
4881 ent->animcache_vertexmesh = NULL;
4882 ent->animcache_vertexmesh_vertexbuffer = NULL;
4883 ent->animcache_vertexmesh_bufferoffset = 0;
4884 ent->animcache_skeletaltransform3x4 = NULL;
4885 ent->animcache_skeletaltransform3x4buffer = NULL;
4886 ent->animcache_skeletaltransform3x4offset = 0;
4887 ent->animcache_skeletaltransform3x4size = 0;
4891 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4895 // check if we need the meshbuffers
4896 if (!vid.useinterleavedarrays)
4899 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4900 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4901 // TODO: upload vertexbuffer?
4902 if (ent->animcache_vertexmesh)
4904 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4905 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4906 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4907 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4908 for (i = 0;i < numvertices;i++)
4909 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4910 if (ent->animcache_svector3f)
4911 for (i = 0;i < numvertices;i++)
4912 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4913 if (ent->animcache_tvector3f)
4914 for (i = 0;i < numvertices;i++)
4915 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4916 if (ent->animcache_normal3f)
4917 for (i = 0;i < numvertices;i++)
4918 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4922 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4924 dp_model_t *model = ent->model;
4927 // see if this ent is worth caching
4928 if (!model || !model->Draw || !model->AnimateVertices)
4930 // nothing to cache if it contains no animations and has no skeleton
4931 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4933 // see if it is already cached for gpuskeletal
4934 if (ent->animcache_skeletaltransform3x4)
4936 // see if it is already cached as a mesh
4937 if (ent->animcache_vertex3f)
4939 // check if we need to add normals or tangents
4940 if (ent->animcache_normal3f)
4941 wantnormals = false;
4942 if (ent->animcache_svector3f)
4943 wanttangents = false;
4944 if (!wantnormals && !wanttangents)
4948 // check which kind of cache we need to generate
4949 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4951 // cache the skeleton so the vertex shader can use it
4952 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4953 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4954 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4955 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4956 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4957 // note: this can fail if the buffer is at the grow limit
4958 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4959 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4961 else if (ent->animcache_vertex3f)
4963 // mesh was already cached but we may need to add normals/tangents
4964 // (this only happens with multiple views, reflections, cameras, etc)
4965 if (wantnormals || wanttangents)
4967 numvertices = model->surfmesh.num_vertices;
4969 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4972 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4973 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4975 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4976 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4977 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4978 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4979 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4984 // generate mesh cache
4985 numvertices = model->surfmesh.num_vertices;
4986 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4988 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4991 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4992 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4994 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4995 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4996 if (wantnormals || wanttangents)
4998 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4999 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5000 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5002 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5003 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5004 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5009 void R_AnimCache_CacheVisibleEntities(void)
5012 qboolean wantnormals = true;
5013 qboolean wanttangents = !r_showsurfaces.integer;
5015 switch(vid.renderpath)
5017 case RENDERPATH_GL20:
5018 case RENDERPATH_D3D9:
5019 case RENDERPATH_D3D10:
5020 case RENDERPATH_D3D11:
5021 case RENDERPATH_GLES2:
5023 case RENDERPATH_GL11:
5024 case RENDERPATH_GL13:
5025 case RENDERPATH_GLES1:
5026 wanttangents = false;
5028 case RENDERPATH_SOFT:
5032 if (r_shownormals.integer)
5033 wanttangents = wantnormals = true;
5035 // TODO: thread this
5036 // NOTE: R_PrepareRTLights() also caches entities
5038 for (i = 0;i < r_refdef.scene.numentities;i++)
5039 if (r_refdef.viewcache.entityvisible[i])
5040 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5043 //==================================================================================
5045 extern cvar_t r_overheadsprites_pushback;
5047 static void R_View_UpdateEntityLighting (void)
5050 entity_render_t *ent;
5051 vec3_t tempdiffusenormal, avg;
5052 vec_t f, fa, fd, fdd;
5053 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5055 for (i = 0;i < r_refdef.scene.numentities;i++)
5057 ent = r_refdef.scene.entities[i];
5059 // skip unseen models
5060 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5064 if (ent->model && ent->model == cl.worldmodel)
5066 // TODO: use modellight for r_ambient settings on world?
5067 VectorSet(ent->modellight_ambient, 0, 0, 0);
5068 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5069 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5073 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5075 // aleady updated by CSQC
5076 // TODO: force modellight on BSP models in this case?
5077 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5081 // fetch the lighting from the worldmodel data
5082 VectorClear(ent->modellight_ambient);
5083 VectorClear(ent->modellight_diffuse);
5084 VectorClear(tempdiffusenormal);
5085 if (ent->flags & RENDER_LIGHT)
5088 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5090 // complete lightning for lit sprites
5091 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5092 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5094 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5095 org[2] = org[2] + r_overheadsprites_pushback.value;
5096 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5099 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5101 if(ent->flags & RENDER_EQUALIZE)
5103 // first fix up ambient lighting...
5104 if(r_equalize_entities_minambient.value > 0)
5106 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5109 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5110 if(fa < r_equalize_entities_minambient.value * fd)
5113 // fa'/fd' = minambient
5114 // fa'+0.25*fd' = fa+0.25*fd
5116 // fa' = fd' * minambient
5117 // fd'*(0.25+minambient) = fa+0.25*fd
5119 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5120 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5122 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5123 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
5124 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5125 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5130 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5132 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5133 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5137 // adjust brightness and saturation to target
5138 avg[0] = avg[1] = avg[2] = fa / f;
5139 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5140 avg[0] = avg[1] = avg[2] = fd / f;
5141 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5147 VectorSet(ent->modellight_ambient, 1, 1, 1);
5150 // move the light direction into modelspace coordinates for lighting code
5151 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5152 if(VectorLength2(ent->modellight_lightdir) == 0)
5153 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5154 VectorNormalize(ent->modellight_lightdir);
5158 #define MAX_LINEOFSIGHTTRACES 64
5160 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5163 vec3_t boxmins, boxmaxs;
5166 dp_model_t *model = r_refdef.scene.worldmodel;
5168 if (!model || !model->brush.TraceLineOfSight)
5171 // expand the box a little
5172 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5173 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5174 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5175 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5176 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5177 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5179 // return true if eye is inside enlarged box
5180 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5184 VectorCopy(eye, start);
5185 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5186 if (model->brush.TraceLineOfSight(model, start, end))
5189 // try various random positions
5190 for (i = 0;i < numsamples;i++)
5192 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5193 if (model->brush.TraceLineOfSight(model, start, end))
5201 static void R_View_UpdateEntityVisible (void)
5206 entity_render_t *ent;
5208 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5209 : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5210 : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL
5211 : RENDER_EXTERIORMODEL;
5212 if (!r_drawviewmodel.integer)
5213 renderimask |= RENDER_VIEWMODEL;
5214 if (!r_drawexteriormodel.integer)
5215 renderimask |= RENDER_EXTERIORMODEL;
5216 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5218 // worldmodel can check visibility
5219 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5220 for (i = 0;i < r_refdef.scene.numentities;i++)
5222 ent = r_refdef.scene.entities[i];
5223 if (!(ent->flags & renderimask))
5224 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)))
5225 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))
5226 r_refdef.viewcache.entityvisible[i] = true;
5231 // no worldmodel or it can't check visibility
5232 for (i = 0;i < r_refdef.scene.numentities;i++)
5234 ent = r_refdef.scene.entities[i];
5235 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));
5238 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5239 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5241 for (i = 0;i < r_refdef.scene.numentities;i++)
5243 if (!r_refdef.viewcache.entityvisible[i])
5245 ent = r_refdef.scene.entities[i];
5246 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5248 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5250 continue; // temp entities do pvs only
5251 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5252 ent->last_trace_visibility = realtime;
5253 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5254 r_refdef.viewcache.entityvisible[i] = 0;
5260 /// only used if skyrendermasked, and normally returns false
5261 static int R_DrawBrushModelsSky (void)
5264 entity_render_t *ent;
5267 for (i = 0;i < r_refdef.scene.numentities;i++)
5269 if (!r_refdef.viewcache.entityvisible[i])
5271 ent = r_refdef.scene.entities[i];
5272 if (!ent->model || !ent->model->DrawSky)
5274 ent->model->DrawSky(ent);
5280 static void R_DrawNoModel(entity_render_t *ent);
5281 static void R_DrawModels(void)
5284 entity_render_t *ent;
5286 for (i = 0;i < r_refdef.scene.numentities;i++)
5288 if (!r_refdef.viewcache.entityvisible[i])
5290 ent = r_refdef.scene.entities[i];
5291 r_refdef.stats[r_stat_entities]++;
5293 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5296 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5297 Con_Printf("R_DrawModels\n");
5298 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]);
5299 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);
5300 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);
5303 if (ent->model && ent->model->Draw != NULL)
5304 ent->model->Draw(ent);
5310 static void R_DrawModelsDepth(void)
5313 entity_render_t *ent;
5315 for (i = 0;i < r_refdef.scene.numentities;i++)
5317 if (!r_refdef.viewcache.entityvisible[i])
5319 ent = r_refdef.scene.entities[i];
5320 if (ent->model && ent->model->DrawDepth != NULL)
5321 ent->model->DrawDepth(ent);
5325 static void R_DrawModelsDebug(void)
5328 entity_render_t *ent;
5330 for (i = 0;i < r_refdef.scene.numentities;i++)
5332 if (!r_refdef.viewcache.entityvisible[i])
5334 ent = r_refdef.scene.entities[i];
5335 if (ent->model && ent->model->DrawDebug != NULL)
5336 ent->model->DrawDebug(ent);
5340 static void R_DrawModelsAddWaterPlanes(void)
5343 entity_render_t *ent;
5345 for (i = 0;i < r_refdef.scene.numentities;i++)
5347 if (!r_refdef.viewcache.entityvisible[i])
5349 ent = r_refdef.scene.entities[i];
5350 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5351 ent->model->DrawAddWaterPlanes(ent);
5355 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}};
5357 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5359 if (r_hdr_irisadaptation.integer)
5364 vec3_t diffusenormal;
5366 vec_t brightness = 0.0f;
5371 VectorCopy(r_refdef.view.forward, forward);
5372 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5374 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5375 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5376 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5377 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5378 d = DotProduct(forward, diffusenormal);
5379 brightness += VectorLength(ambient);
5381 brightness += d * VectorLength(diffuse);
5383 brightness *= 1.0f / c;
5384 brightness += 0.00001f; // make sure it's never zero
5385 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5386 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5387 current = r_hdr_irisadaptation_value.value;
5389 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5390 else if (current > goal)
5391 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5392 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5393 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5395 else if (r_hdr_irisadaptation_value.value != 1.0f)
5396 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5399 static void R_View_SetFrustum(const int *scissor)
5402 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5403 vec3_t forward, left, up, origin, v;
5407 // flipped x coordinates (because x points left here)
5408 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5409 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5411 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5412 switch(vid.renderpath)
5414 case RENDERPATH_D3D9:
5415 case RENDERPATH_D3D10:
5416 case RENDERPATH_D3D11:
5417 // non-flipped y coordinates
5418 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5419 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5421 case RENDERPATH_SOFT:
5422 case RENDERPATH_GL11:
5423 case RENDERPATH_GL13:
5424 case RENDERPATH_GL20:
5425 case RENDERPATH_GLES1:
5426 case RENDERPATH_GLES2:
5427 // non-flipped y coordinates
5428 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5429 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5434 // we can't trust r_refdef.view.forward and friends in reflected scenes
5435 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5438 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5439 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5440 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5441 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5442 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5443 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5444 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5445 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5446 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5447 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5448 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5449 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5453 zNear = r_refdef.nearclip;
5454 nudge = 1.0 - 1.0 / (1<<23);
5455 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5456 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5457 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5458 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5459 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5460 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5461 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5462 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5468 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5469 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5470 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5471 r_refdef.view.frustum[0].dist = m[15] - m[12];
5473 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5474 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5475 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5476 r_refdef.view.frustum[1].dist = m[15] + m[12];
5478 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5479 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5480 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5481 r_refdef.view.frustum[2].dist = m[15] - m[13];
5483 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5484 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5485 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5486 r_refdef.view.frustum[3].dist = m[15] + m[13];
5488 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5489 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5490 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5491 r_refdef.view.frustum[4].dist = m[15] - m[14];
5493 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5494 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5495 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5496 r_refdef.view.frustum[5].dist = m[15] + m[14];
5499 if (r_refdef.view.useperspective)
5501 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5502 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]);
5503 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]);
5504 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]);
5505 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]);
5507 // then the normals from the corners relative to origin
5508 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5509 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5510 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5511 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5513 // in a NORMAL view, forward cross left == up
5514 // in a REFLECTED view, forward cross left == down
5515 // so our cross products above need to be adjusted for a left handed coordinate system
5516 CrossProduct(forward, left, v);
5517 if(DotProduct(v, up) < 0)
5519 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5520 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5521 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5522 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5525 // Leaving those out was a mistake, those were in the old code, and they
5526 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5527 // I couldn't reproduce it after adding those normalizations. --blub
5528 VectorNormalize(r_refdef.view.frustum[0].normal);
5529 VectorNormalize(r_refdef.view.frustum[1].normal);
5530 VectorNormalize(r_refdef.view.frustum[2].normal);
5531 VectorNormalize(r_refdef.view.frustum[3].normal);
5533 // make the corners absolute
5534 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5535 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5536 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5537 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5540 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5542 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5543 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5544 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5545 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5546 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5550 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5551 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5552 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5553 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5554 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5555 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5556 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5557 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5558 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5559 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5561 r_refdef.view.numfrustumplanes = 5;
5563 if (r_refdef.view.useclipplane)
5565 r_refdef.view.numfrustumplanes = 6;
5566 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5569 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5570 PlaneClassify(r_refdef.view.frustum + i);
5572 // LordHavoc: note to all quake engine coders, Quake had a special case
5573 // for 90 degrees which assumed a square view (wrong), so I removed it,
5574 // Quake2 has it disabled as well.
5576 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5577 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5578 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5579 //PlaneClassify(&frustum[0]);
5581 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5582 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5583 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5584 //PlaneClassify(&frustum[1]);
5586 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5587 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5588 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5589 //PlaneClassify(&frustum[2]);
5591 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5592 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5593 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5594 //PlaneClassify(&frustum[3]);
5597 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5598 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5599 //PlaneClassify(&frustum[4]);
5602 static void R_View_UpdateWithScissor(const int *myscissor)
5604 R_Main_ResizeViewCache();
5605 R_View_SetFrustum(myscissor);
5606 R_View_WorldVisibility(r_refdef.view.useclipplane);
5607 R_View_UpdateEntityVisible();
5608 R_View_UpdateEntityLighting();
5611 static void R_View_Update(void)
5613 R_Main_ResizeViewCache();
5614 R_View_SetFrustum(NULL);
5615 R_View_WorldVisibility(r_refdef.view.useclipplane);
5616 R_View_UpdateEntityVisible();
5617 R_View_UpdateEntityLighting();
5620 float viewscalefpsadjusted = 1.0f;
5622 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5624 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5625 scale = bound(0.03125f, scale, 1.0f);
5626 *outwidth = (int)ceil(width * scale);
5627 *outheight = (int)ceil(height * scale);
5630 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5632 const float *customclipplane = NULL;
5634 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5635 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5637 // LordHavoc: couldn't figure out how to make this approach the
5638 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5639 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5640 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5641 dist = r_refdef.view.clipplane.dist;
5642 plane[0] = r_refdef.view.clipplane.normal[0];
5643 plane[1] = r_refdef.view.clipplane.normal[1];
5644 plane[2] = r_refdef.view.clipplane.normal[2];
5646 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5649 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5650 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5652 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5653 if (!r_refdef.view.useperspective)
5654 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);
5655 else if (vid.stencil && r_useinfinitefarclip.integer)
5656 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);
5658 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);
5659 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5660 R_SetViewport(&r_refdef.view.viewport);
5661 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5663 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5664 float screenplane[4];
5665 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5666 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5667 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5668 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5669 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5673 void R_EntityMatrix(const matrix4x4_t *matrix)
5675 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5677 gl_modelmatrixchanged = false;
5678 gl_modelmatrix = *matrix;
5679 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5680 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5681 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5682 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5684 switch(vid.renderpath)
5686 case RENDERPATH_D3D9:
5688 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5689 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5692 case RENDERPATH_D3D10:
5693 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5695 case RENDERPATH_D3D11:
5696 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5698 case RENDERPATH_GL11:
5699 case RENDERPATH_GL13:
5700 case RENDERPATH_GLES1:
5702 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5705 case RENDERPATH_SOFT:
5706 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5707 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5709 case RENDERPATH_GL20:
5710 case RENDERPATH_GLES2:
5711 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5712 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5718 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5720 r_viewport_t viewport;
5724 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5725 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);
5726 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5727 R_SetViewport(&viewport);
5728 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5729 GL_Color(1, 1, 1, 1);
5730 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5731 GL_BlendFunc(GL_ONE, GL_ZERO);
5732 GL_ScissorTest(false);
5733 GL_DepthMask(false);
5734 GL_DepthRange(0, 1);
5735 GL_DepthTest(false);
5736 GL_DepthFunc(GL_LEQUAL);
5737 R_EntityMatrix(&identitymatrix);
5738 R_Mesh_ResetTextureState();
5739 GL_PolygonOffset(0, 0);
5740 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5741 switch(vid.renderpath)
5743 case RENDERPATH_GL11:
5744 case RENDERPATH_GL13:
5745 case RENDERPATH_GL20:
5746 case RENDERPATH_GLES1:
5747 case RENDERPATH_GLES2:
5748 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5750 case RENDERPATH_D3D9:
5751 case RENDERPATH_D3D10:
5752 case RENDERPATH_D3D11:
5753 case RENDERPATH_SOFT:
5756 GL_CullFace(GL_NONE);
5761 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5765 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5768 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5772 R_SetupView(true, fbo, depthtexture, colortexture);
5773 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5774 GL_Color(1, 1, 1, 1);
5775 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5776 GL_BlendFunc(GL_ONE, GL_ZERO);
5777 GL_ScissorTest(true);
5779 GL_DepthRange(0, 1);
5781 GL_DepthFunc(GL_LEQUAL);
5782 R_EntityMatrix(&identitymatrix);
5783 R_Mesh_ResetTextureState();
5784 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5785 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5786 switch(vid.renderpath)
5788 case RENDERPATH_GL11:
5789 case RENDERPATH_GL13:
5790 case RENDERPATH_GL20:
5791 case RENDERPATH_GLES1:
5792 case RENDERPATH_GLES2:
5793 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5795 case RENDERPATH_D3D9:
5796 case RENDERPATH_D3D10:
5797 case RENDERPATH_D3D11:
5798 case RENDERPATH_SOFT:
5801 GL_CullFace(r_refdef.view.cullface_back);
5806 R_RenderView_UpdateViewVectors
5809 void R_RenderView_UpdateViewVectors(void)
5811 // break apart the view matrix into vectors for various purposes
5812 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5813 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5814 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5815 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5816 // make an inverted copy of the view matrix for tracking sprites
5817 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5820 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5821 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5823 static void R_Water_StartFrame(void)
5826 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5827 r_waterstate_waterplane_t *p;
5828 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;
5830 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5833 switch(vid.renderpath)
5835 case RENDERPATH_GL20:
5836 case RENDERPATH_D3D9:
5837 case RENDERPATH_D3D10:
5838 case RENDERPATH_D3D11:
5839 case RENDERPATH_SOFT:
5840 case RENDERPATH_GLES2:
5842 case RENDERPATH_GL11:
5843 case RENDERPATH_GL13:
5844 case RENDERPATH_GLES1:
5848 // set waterwidth and waterheight to the water resolution that will be
5849 // used (often less than the screen resolution for faster rendering)
5850 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5852 // calculate desired texture sizes
5853 // can't use water if the card does not support the texture size
5854 if (!r_water.integer || r_showsurfaces.integer)
5855 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5856 else if (vid.support.arb_texture_non_power_of_two)
5858 texturewidth = waterwidth;
5859 textureheight = waterheight;
5860 camerawidth = waterwidth;
5861 cameraheight = waterheight;
5865 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5866 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5867 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5868 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5871 // allocate textures as needed
5872 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))
5874 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5875 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5877 if (p->texture_refraction)
5878 R_FreeTexture(p->texture_refraction);
5879 p->texture_refraction = NULL;
5880 if (p->fbo_refraction)
5881 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5882 p->fbo_refraction = 0;
5883 if (p->texture_reflection)
5884 R_FreeTexture(p->texture_reflection);
5885 p->texture_reflection = NULL;
5886 if (p->fbo_reflection)
5887 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5888 p->fbo_reflection = 0;
5889 if (p->texture_camera)
5890 R_FreeTexture(p->texture_camera);
5891 p->texture_camera = NULL;
5893 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5896 memset(&r_fb.water, 0, sizeof(r_fb.water));
5897 r_fb.water.texturewidth = texturewidth;
5898 r_fb.water.textureheight = textureheight;
5899 r_fb.water.camerawidth = camerawidth;
5900 r_fb.water.cameraheight = cameraheight;
5903 if (r_fb.water.texturewidth)
5905 int scaledwidth, scaledheight;
5907 r_fb.water.enabled = true;
5909 // water resolution is usually reduced
5910 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5911 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5912 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5914 // set up variables that will be used in shader setup
5915 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5916 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5917 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5918 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5921 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5922 r_fb.water.numwaterplanes = 0;
5925 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5927 int planeindex, bestplaneindex, vertexindex;
5928 vec3_t mins, maxs, normal, center, v, n;
5929 vec_t planescore, bestplanescore;
5931 r_waterstate_waterplane_t *p;
5932 texture_t *t = R_GetCurrentTexture(surface->texture);
5934 rsurface.texture = t;
5935 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5936 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5937 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5939 // average the vertex normals, find the surface bounds (after deformvertexes)
5940 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5941 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5942 VectorCopy(n, normal);
5943 VectorCopy(v, mins);
5944 VectorCopy(v, maxs);
5945 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5947 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5948 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5949 VectorAdd(normal, n, normal);
5950 mins[0] = min(mins[0], v[0]);
5951 mins[1] = min(mins[1], v[1]);
5952 mins[2] = min(mins[2], v[2]);
5953 maxs[0] = max(maxs[0], v[0]);
5954 maxs[1] = max(maxs[1], v[1]);
5955 maxs[2] = max(maxs[2], v[2]);
5957 VectorNormalize(normal);
5958 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5960 VectorCopy(normal, plane.normal);
5961 VectorNormalize(plane.normal);
5962 plane.dist = DotProduct(center, plane.normal);
5963 PlaneClassify(&plane);
5964 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5966 // skip backfaces (except if nocullface is set)
5967 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5969 VectorNegate(plane.normal, plane.normal);
5971 PlaneClassify(&plane);
5975 // find a matching plane if there is one
5976 bestplaneindex = -1;
5977 bestplanescore = 1048576.0f;
5978 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5980 if(p->camera_entity == t->camera_entity)
5982 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5983 if (bestplaneindex < 0 || bestplanescore > planescore)
5985 bestplaneindex = planeindex;
5986 bestplanescore = planescore;
5990 planeindex = bestplaneindex;
5991 p = r_fb.water.waterplanes + planeindex;
5993 // if this surface does not fit any known plane rendered this frame, add one
5994 if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5996 // store the new plane
5997 planeindex = r_fb.water.numwaterplanes++;
5998 p = r_fb.water.waterplanes + planeindex;
6000 // clear materialflags and pvs
6001 p->materialflags = 0;
6002 p->pvsvalid = false;
6003 p->camera_entity = t->camera_entity;
6004 VectorCopy(mins, p->mins);
6005 VectorCopy(maxs, p->maxs);
6009 // merge mins/maxs when we're adding this surface to the plane
6010 p->mins[0] = min(p->mins[0], mins[0]);
6011 p->mins[1] = min(p->mins[1], mins[1]);
6012 p->mins[2] = min(p->mins[2], mins[2]);
6013 p->maxs[0] = max(p->maxs[0], maxs[0]);
6014 p->maxs[1] = max(p->maxs[1], maxs[1]);
6015 p->maxs[2] = max(p->maxs[2], maxs[2]);
6017 // merge this surface's materialflags into the waterplane
6018 p->materialflags |= t->currentmaterialflags;
6019 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6021 // merge this surface's PVS into the waterplane
6022 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6023 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6025 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6031 extern cvar_t r_drawparticles;
6032 extern cvar_t r_drawdecals;
6034 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6037 r_refdef_view_t originalview;
6038 r_refdef_view_t myview;
6039 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;
6040 r_waterstate_waterplane_t *p;
6042 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;
6045 originalview = r_refdef.view;
6047 // lowquality hack, temporarily shut down some cvars and restore afterwards
6048 qualityreduction = r_water_lowquality.integer;
6049 if (qualityreduction > 0)
6051 if (qualityreduction >= 1)
6053 old_r_shadows = r_shadows.integer;
6054 old_r_worldrtlight = r_shadow_realtime_world.integer;
6055 old_r_dlight = r_shadow_realtime_dlight.integer;
6056 Cvar_SetValueQuick(&r_shadows, 0);
6057 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6058 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6060 if (qualityreduction >= 2)
6062 old_r_dynamic = r_dynamic.integer;
6063 old_r_particles = r_drawparticles.integer;
6064 old_r_decals = r_drawdecals.integer;
6065 Cvar_SetValueQuick(&r_dynamic, 0);
6066 Cvar_SetValueQuick(&r_drawparticles, 0);
6067 Cvar_SetValueQuick(&r_drawdecals, 0);
6071 // make sure enough textures are allocated
6072 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6074 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6076 if (!p->texture_refraction)
6077 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);
6078 if (!p->texture_refraction)
6082 if (r_fb.water.depthtexture == NULL)
6083 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6084 if (p->fbo_refraction == 0)
6085 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6088 else if (p->materialflags & MATERIALFLAG_CAMERA)
6090 if (!p->texture_camera)
6091 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);
6092 if (!p->texture_camera)
6096 if (r_fb.water.depthtexture == NULL)
6097 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6098 if (p->fbo_camera == 0)
6099 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6103 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6105 if (!p->texture_reflection)
6106 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);
6107 if (!p->texture_reflection)
6111 if (r_fb.water.depthtexture == NULL)
6112 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6113 if (p->fbo_reflection == 0)
6114 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6120 r_refdef.view = originalview;
6121 r_refdef.view.showdebug = false;
6122 r_refdef.view.width = r_fb.water.waterwidth;
6123 r_refdef.view.height = r_fb.water.waterheight;
6124 r_refdef.view.useclipplane = true;
6125 myview = r_refdef.view;
6126 r_fb.water.renderingscene = true;
6127 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6129 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6131 r_refdef.view = myview;
6132 if(r_water_scissormode.integer)
6134 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6135 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6136 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6139 // render reflected scene and copy into texture
6140 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6141 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6142 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6143 r_refdef.view.clipplane = p->plane;
6144 // reverse the cullface settings for this render
6145 r_refdef.view.cullface_front = GL_FRONT;
6146 r_refdef.view.cullface_back = GL_BACK;
6147 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6149 r_refdef.view.usecustompvs = true;
6151 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6153 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6156 r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6157 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6158 R_ClearScreen(r_refdef.fogenabled);
6159 if(r_water_scissormode.integer & 2)
6160 R_View_UpdateWithScissor(myscissor);
6163 R_AnimCache_CacheVisibleEntities();
6164 if(r_water_scissormode.integer & 1)
6165 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6166 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6168 if (!p->fbo_reflection)
6169 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);
6170 r_fb.water.hideplayer = false;
6173 // render the normal view scene and copy into texture
6174 // (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)
6175 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6177 r_refdef.view = myview;
6178 if(r_water_scissormode.integer)
6180 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6181 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6182 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6185 r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6187 r_refdef.view.clipplane = p->plane;
6188 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6189 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6191 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6193 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6194 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6195 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6196 R_RenderView_UpdateViewVectors();
6197 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6199 r_refdef.view.usecustompvs = true;
6200 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);
6204 PlaneClassify(&r_refdef.view.clipplane);
6206 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6207 R_ClearScreen(r_refdef.fogenabled);
6208 if(r_water_scissormode.integer & 2)
6209 R_View_UpdateWithScissor(myscissor);
6212 R_AnimCache_CacheVisibleEntities();
6213 if(r_water_scissormode.integer & 1)
6214 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6215 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6217 if (!p->fbo_refraction)
6218 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);
6219 r_fb.water.hideplayer = false;
6221 else if (p->materialflags & MATERIALFLAG_CAMERA)
6223 r_refdef.view = myview;
6225 r_refdef.view.clipplane = p->plane;
6226 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6227 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6229 r_refdef.view.width = r_fb.water.camerawidth;
6230 r_refdef.view.height = r_fb.water.cameraheight;
6231 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6232 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6233 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6234 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6236 if(p->camera_entity)
6238 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6239 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6242 // note: all of the view is used for displaying... so
6243 // there is no use in scissoring
6245 // reverse the cullface settings for this render
6246 r_refdef.view.cullface_front = GL_FRONT;
6247 r_refdef.view.cullface_back = GL_BACK;
6248 // also reverse the view matrix
6249 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
6250 R_RenderView_UpdateViewVectors();
6251 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6253 r_refdef.view.usecustompvs = true;
6254 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);
6257 // camera needs no clipplane
6258 r_refdef.view.useclipplane = false;
6260 PlaneClassify(&r_refdef.view.clipplane);
6262 r_fb.water.hideplayer = false;
6264 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6265 R_ClearScreen(r_refdef.fogenabled);
6267 R_AnimCache_CacheVisibleEntities();
6268 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6271 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);
6272 r_fb.water.hideplayer = false;
6276 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6277 r_fb.water.renderingscene = false;
6278 r_refdef.view = originalview;
6279 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6280 if (!r_fb.water.depthtexture)
6281 R_ClearScreen(r_refdef.fogenabled);
6283 R_AnimCache_CacheVisibleEntities();
6286 r_refdef.view = originalview;
6287 r_fb.water.renderingscene = false;
6288 Cvar_SetValueQuick(&r_water, 0);
6289 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6291 // lowquality hack, restore cvars
6292 if (qualityreduction > 0)
6294 if (qualityreduction >= 1)
6296 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6297 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6298 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6300 if (qualityreduction >= 2)
6302 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6303 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6304 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6309 static void R_Bloom_StartFrame(void)
6312 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6313 int viewwidth, viewheight;
6314 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6315 textype_t textype = TEXTYPE_COLORBUFFER;
6317 switch (vid.renderpath)
6319 case RENDERPATH_GL20:
6320 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6321 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6323 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6324 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6327 case RENDERPATH_GL11:
6328 case RENDERPATH_GL13:
6329 case RENDERPATH_GLES1:
6330 case RENDERPATH_GLES2:
6331 case RENDERPATH_D3D9:
6332 case RENDERPATH_D3D10:
6333 case RENDERPATH_D3D11:
6334 r_fb.usedepthtextures = false;
6336 case RENDERPATH_SOFT:
6337 r_fb.usedepthtextures = true;
6341 if (r_viewscale_fpsscaling.integer)
6343 double actualframetime;
6344 double targetframetime;
6346 actualframetime = r_refdef.lastdrawscreentime;
6347 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6348 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6349 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6350 if (r_viewscale_fpsscaling_stepsize.value > 0)
6351 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6352 viewscalefpsadjusted += adjust;
6353 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6356 viewscalefpsadjusted = 1.0f;
6358 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6360 switch(vid.renderpath)
6362 case RENDERPATH_GL20:
6363 case RENDERPATH_D3D9:
6364 case RENDERPATH_D3D10:
6365 case RENDERPATH_D3D11:
6366 case RENDERPATH_SOFT:
6367 case RENDERPATH_GLES2:
6369 case RENDERPATH_GL11:
6370 case RENDERPATH_GL13:
6371 case RENDERPATH_GLES1:
6375 // set bloomwidth and bloomheight to the bloom resolution that will be
6376 // used (often less than the screen resolution for faster rendering)
6377 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6378 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6379 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6380 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6381 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6383 // calculate desired texture sizes
6384 if (vid.support.arb_texture_non_power_of_two)
6386 screentexturewidth = vid.width;
6387 screentextureheight = vid.height;
6388 bloomtexturewidth = r_fb.bloomwidth;
6389 bloomtextureheight = r_fb.bloomheight;
6393 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6394 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6395 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6396 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6399 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))
6401 Cvar_SetValueQuick(&r_bloom, 0);
6402 Cvar_SetValueQuick(&r_motionblur, 0);
6403 Cvar_SetValueQuick(&r_damageblur, 0);
6406 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6408 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6410 && r_viewscale.value == 1.0f
6411 && !r_viewscale_fpsscaling.integer)
6412 screentexturewidth = screentextureheight = 0;
6413 if (!r_bloom.integer)
6414 bloomtexturewidth = bloomtextureheight = 0;
6416 // allocate textures as needed
6417 if (r_fb.screentexturewidth != screentexturewidth
6418 || r_fb.screentextureheight != screentextureheight
6419 || r_fb.bloomtexturewidth != bloomtexturewidth
6420 || r_fb.bloomtextureheight != bloomtextureheight
6421 || r_fb.textype != textype
6422 || useviewfbo != (r_fb.fbo != 0))
6424 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6426 if (r_fb.bloomtexture[i])
6427 R_FreeTexture(r_fb.bloomtexture[i]);
6428 r_fb.bloomtexture[i] = NULL;
6430 if (r_fb.bloomfbo[i])
6431 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6432 r_fb.bloomfbo[i] = 0;
6436 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6439 if (r_fb.colortexture)
6440 R_FreeTexture(r_fb.colortexture);
6441 r_fb.colortexture = NULL;
6443 if (r_fb.depthtexture)
6444 R_FreeTexture(r_fb.depthtexture);
6445 r_fb.depthtexture = NULL;
6447 if (r_fb.ghosttexture)
6448 R_FreeTexture(r_fb.ghosttexture);
6449 r_fb.ghosttexture = NULL;
6451 r_fb.screentexturewidth = screentexturewidth;
6452 r_fb.screentextureheight = screentextureheight;
6453 r_fb.bloomtexturewidth = bloomtexturewidth;
6454 r_fb.bloomtextureheight = bloomtextureheight;
6455 r_fb.textype = textype;
6457 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6459 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6460 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);
6461 r_fb.ghosttexture_valid = false;
6462 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);
6465 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6466 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6467 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6471 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6473 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6475 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);
6477 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6482 // bloom texture is a different resolution
6483 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6484 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6485 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6486 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6487 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6489 // set up a texcoord array for the full resolution screen image
6490 // (we have to keep this around to copy back during final render)
6491 r_fb.screentexcoord2f[0] = 0;
6492 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6493 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6494 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6495 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6496 r_fb.screentexcoord2f[5] = 0;
6497 r_fb.screentexcoord2f[6] = 0;
6498 r_fb.screentexcoord2f[7] = 0;
6502 for (i = 1;i < 8;i += 2)
6504 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6508 // set up a texcoord array for the reduced resolution bloom image
6509 // (which will be additive blended over the screen image)
6510 r_fb.bloomtexcoord2f[0] = 0;
6511 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6512 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6513 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6514 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6515 r_fb.bloomtexcoord2f[5] = 0;
6516 r_fb.bloomtexcoord2f[6] = 0;
6517 r_fb.bloomtexcoord2f[7] = 0;
6519 switch(vid.renderpath)
6521 case RENDERPATH_GL11:
6522 case RENDERPATH_GL13:
6523 case RENDERPATH_GL20:
6524 case RENDERPATH_SOFT:
6525 case RENDERPATH_GLES1:
6526 case RENDERPATH_GLES2:
6528 case RENDERPATH_D3D9:
6529 case RENDERPATH_D3D10:
6530 case RENDERPATH_D3D11:
6531 for (i = 0;i < 4;i++)
6533 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6534 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6535 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6536 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6541 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6544 r_refdef.view.clear = true;
6547 static void R_Bloom_MakeTexture(void)
6550 float xoffset, yoffset, r, brighten;
6552 float colorscale = r_bloom_colorscale.value;
6554 r_refdef.stats[r_stat_bloom]++;
6557 // this copy is unnecessary since it happens in R_BlendView already
6560 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);
6561 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6565 // scale down screen texture to the bloom texture size
6567 r_fb.bloomindex = 0;
6568 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6569 R_SetViewport(&r_fb.bloomviewport);
6570 GL_DepthTest(false);
6571 GL_BlendFunc(GL_ONE, GL_ZERO);
6572 GL_Color(colorscale, colorscale, colorscale, 1);
6573 // 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...
6574 switch(vid.renderpath)
6576 case RENDERPATH_GL11:
6577 case RENDERPATH_GL13:
6578 case RENDERPATH_GL20:
6579 case RENDERPATH_GLES1:
6580 case RENDERPATH_GLES2:
6581 case RENDERPATH_SOFT:
6582 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6584 case RENDERPATH_D3D9:
6585 case RENDERPATH_D3D10:
6586 case RENDERPATH_D3D11:
6587 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6590 // TODO: do boxfilter scale-down in shader?
6591 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6592 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6593 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6595 // we now have a properly scaled bloom image
6596 if (!r_fb.bloomfbo[r_fb.bloomindex])
6598 // copy it into the bloom texture
6599 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);
6600 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6603 // multiply bloom image by itself as many times as desired
6604 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6606 intex = r_fb.bloomtexture[r_fb.bloomindex];
6607 r_fb.bloomindex ^= 1;
6608 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6610 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6611 if (!r_fb.bloomfbo[r_fb.bloomindex])
6613 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6614 GL_Color(r,r,r,1); // apply fix factor
6619 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6620 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6621 GL_Color(1,1,1,1); // no fix factor supported here
6623 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6624 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6625 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6626 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6628 if (!r_fb.bloomfbo[r_fb.bloomindex])
6630 // copy the darkened image to a texture
6631 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);
6632 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6636 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6637 brighten = r_bloom_brighten.value;
6638 brighten = sqrt(brighten);
6640 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6642 for (dir = 0;dir < 2;dir++)
6644 intex = r_fb.bloomtexture[r_fb.bloomindex];
6645 r_fb.bloomindex ^= 1;
6646 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6647 // blend on at multiple vertical offsets to achieve a vertical blur
6648 // TODO: do offset blends using GLSL
6649 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6650 GL_BlendFunc(GL_ONE, GL_ZERO);
6651 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6652 for (x = -range;x <= range;x++)
6654 if (!dir){xoffset = 0;yoffset = x;}
6655 else {xoffset = x;yoffset = 0;}
6656 xoffset /= (float)r_fb.bloomtexturewidth;
6657 yoffset /= (float)r_fb.bloomtextureheight;
6658 // compute a texcoord array with the specified x and y offset
6659 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6660 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6661 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6662 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6663 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6664 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6665 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6666 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6667 // this r value looks like a 'dot' particle, fading sharply to
6668 // black at the edges
6669 // (probably not realistic but looks good enough)
6670 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6671 //r = brighten/(range*2+1);
6672 r = brighten / (range * 2 + 1);
6674 r *= (1 - x*x/(float)(range*range));
6675 GL_Color(r, r, r, 1);
6676 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6677 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6678 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6679 GL_BlendFunc(GL_ONE, GL_ONE);
6682 if (!r_fb.bloomfbo[r_fb.bloomindex])
6684 // copy the vertically or horizontally blurred bloom view to a texture
6685 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);
6686 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6691 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6693 unsigned int permutation;
6694 float uservecs[4][4];
6696 R_EntityMatrix(&identitymatrix);
6698 switch (vid.renderpath)
6700 case RENDERPATH_GL20:
6701 case RENDERPATH_D3D9:
6702 case RENDERPATH_D3D10:
6703 case RENDERPATH_D3D11:
6704 case RENDERPATH_SOFT:
6705 case RENDERPATH_GLES2:
6707 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6708 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6709 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6710 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6711 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6713 if (r_fb.colortexture)
6717 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);
6718 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6721 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6723 // declare variables
6724 float blur_factor, blur_mouseaccel, blur_velocity;
6725 static float blur_average;
6726 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6728 // set a goal for the factoring
6729 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6730 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6731 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6732 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6733 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6734 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6736 // from the goal, pick an averaged value between goal and last value
6737 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6738 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6740 // enforce minimum amount of blur
6741 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6743 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6745 // calculate values into a standard alpha
6746 cl.motionbluralpha = 1 - exp(-
6748 (r_motionblur.value * blur_factor / 80)
6750 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6753 max(0.0001, cl.time - cl.oldtime) // fps independent
6756 // randomization for the blur value to combat persistent ghosting
6757 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6758 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6761 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6762 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6764 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6765 GL_Color(1, 1, 1, cl.motionbluralpha);
6766 switch(vid.renderpath)
6768 case RENDERPATH_GL11:
6769 case RENDERPATH_GL13:
6770 case RENDERPATH_GL20:
6771 case RENDERPATH_GLES1:
6772 case RENDERPATH_GLES2:
6773 case RENDERPATH_SOFT:
6774 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6776 case RENDERPATH_D3D9:
6777 case RENDERPATH_D3D10:
6778 case RENDERPATH_D3D11:
6779 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6782 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6783 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6784 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6787 // updates old view angles for next pass
6788 VectorCopy(cl.viewangles, blur_oldangles);
6790 // copy view into the ghost texture
6791 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);
6792 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6793 r_fb.ghosttexture_valid = true;
6798 // no r_fb.colortexture means we're rendering to the real fb
6799 // we may still have to do view tint...
6800 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6802 // apply a color tint to the whole view
6803 R_ResetViewRendering2D(0, NULL, NULL);
6804 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6805 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6806 R_SetupShader_Generic_NoTexture(false, true);
6807 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6808 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6810 break; // no screen processing, no bloom, skip it
6813 if (r_fb.bloomtexture[0])
6815 // make the bloom texture
6816 R_Bloom_MakeTexture();
6819 #if _MSC_VER >= 1400
6820 #define sscanf sscanf_s
6822 memset(uservecs, 0, sizeof(uservecs));
6823 if (r_glsl_postprocess_uservec1_enable.integer)
6824 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6825 if (r_glsl_postprocess_uservec2_enable.integer)
6826 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6827 if (r_glsl_postprocess_uservec3_enable.integer)
6828 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6829 if (r_glsl_postprocess_uservec4_enable.integer)
6830 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6832 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6833 GL_Color(1, 1, 1, 1);
6834 GL_BlendFunc(GL_ONE, GL_ZERO);
6836 switch(vid.renderpath)
6838 case RENDERPATH_GL20:
6839 case RENDERPATH_GLES2:
6840 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6841 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6842 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6843 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6844 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6845 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]);
6846 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6847 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]);
6848 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]);
6849 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]);
6850 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]);
6851 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6852 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6853 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);
6855 case RENDERPATH_D3D9:
6857 // 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...
6858 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6859 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6860 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6861 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6862 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6863 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6864 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6865 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6866 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6867 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6868 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6869 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6870 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6871 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6874 case RENDERPATH_D3D10:
6875 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6877 case RENDERPATH_D3D11:
6878 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6880 case RENDERPATH_SOFT:
6881 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6882 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6883 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6884 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6885 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6886 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6887 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6888 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6889 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6890 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6891 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6892 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6893 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6894 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6899 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6900 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6902 case RENDERPATH_GL11:
6903 case RENDERPATH_GL13:
6904 case RENDERPATH_GLES1:
6905 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6907 // apply a color tint to the whole view
6908 R_ResetViewRendering2D(0, NULL, NULL);
6909 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6910 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6911 R_SetupShader_Generic_NoTexture(false, true);
6912 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6913 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6919 matrix4x4_t r_waterscrollmatrix;
6921 void R_UpdateFog(void)
6924 if (gamemode == GAME_NEHAHRA)
6926 if (gl_fogenable.integer)
6928 r_refdef.oldgl_fogenable = true;
6929 r_refdef.fog_density = gl_fogdensity.value;
6930 r_refdef.fog_red = gl_fogred.value;
6931 r_refdef.fog_green = gl_foggreen.value;
6932 r_refdef.fog_blue = gl_fogblue.value;
6933 r_refdef.fog_alpha = 1;
6934 r_refdef.fog_start = 0;
6935 r_refdef.fog_end = gl_skyclip.value;
6936 r_refdef.fog_height = 1<<30;
6937 r_refdef.fog_fadedepth = 128;
6939 else if (r_refdef.oldgl_fogenable)
6941 r_refdef.oldgl_fogenable = false;
6942 r_refdef.fog_density = 0;
6943 r_refdef.fog_red = 0;
6944 r_refdef.fog_green = 0;
6945 r_refdef.fog_blue = 0;
6946 r_refdef.fog_alpha = 0;
6947 r_refdef.fog_start = 0;
6948 r_refdef.fog_end = 0;
6949 r_refdef.fog_height = 1<<30;
6950 r_refdef.fog_fadedepth = 128;
6955 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6956 r_refdef.fog_start = max(0, r_refdef.fog_start);
6957 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6959 if (r_refdef.fog_density && r_drawfog.integer)
6961 r_refdef.fogenabled = true;
6962 // this is the point where the fog reaches 0.9986 alpha, which we
6963 // consider a good enough cutoff point for the texture
6964 // (0.9986 * 256 == 255.6)
6965 if (r_fog_exp2.integer)
6966 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6968 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6969 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6970 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6971 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6972 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6973 R_BuildFogHeightTexture();
6974 // fog color was already set
6975 // update the fog texture
6976 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)
6977 R_BuildFogTexture();
6978 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6979 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6982 r_refdef.fogenabled = false;
6985 if (r_refdef.fog_density)
6987 r_refdef.fogcolor[0] = r_refdef.fog_red;
6988 r_refdef.fogcolor[1] = r_refdef.fog_green;
6989 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6991 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6992 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6993 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6994 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6998 VectorCopy(r_refdef.fogcolor, fogvec);
6999 // color.rgb *= ContrastBoost * SceneBrightness;
7000 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7001 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7002 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7003 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7008 void R_UpdateVariables(void)
7012 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7014 r_refdef.farclip = r_farclip_base.value;
7015 if (r_refdef.scene.worldmodel)
7016 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7017 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7019 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7020 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7021 r_refdef.polygonfactor = 0;
7022 r_refdef.polygonoffset = 0;
7023 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7024 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7026 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7027 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7028 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7029 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7030 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7031 if (FAKELIGHT_ENABLED)
7033 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7035 else if (r_refdef.scene.worldmodel)
7037 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7039 if (r_showsurfaces.integer)
7041 r_refdef.scene.rtworld = false;
7042 r_refdef.scene.rtworldshadows = false;
7043 r_refdef.scene.rtdlight = false;
7044 r_refdef.scene.rtdlightshadows = false;
7045 r_refdef.lightmapintensity = 0;
7048 r_gpuskeletal = false;
7049 switch(vid.renderpath)
7051 case RENDERPATH_GL20:
7052 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7053 case RENDERPATH_D3D9:
7054 case RENDERPATH_D3D10:
7055 case RENDERPATH_D3D11:
7056 case RENDERPATH_SOFT:
7057 case RENDERPATH_GLES2:
7058 if(v_glslgamma.integer && !vid_gammatables_trivial)
7060 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7062 // build GLSL gamma texture
7063 #define RAMPWIDTH 256
7064 unsigned short ramp[RAMPWIDTH * 3];
7065 unsigned char rampbgr[RAMPWIDTH][4];
7068 r_texture_gammaramps_serial = vid_gammatables_serial;
7070 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7071 for(i = 0; i < RAMPWIDTH; ++i)
7073 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7074 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7075 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7078 if (r_texture_gammaramps)
7080 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7084 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7090 // remove GLSL gamma texture
7093 case RENDERPATH_GL11:
7094 case RENDERPATH_GL13:
7095 case RENDERPATH_GLES1:
7100 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7101 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7107 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7108 if( scenetype != r_currentscenetype ) {
7109 // store the old scenetype
7110 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7111 r_currentscenetype = scenetype;
7112 // move in the new scene
7113 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7122 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7124 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7125 if( scenetype == r_currentscenetype ) {
7126 return &r_refdef.scene;
7128 return &r_scenes_store[ scenetype ];
7132 static int R_SortEntities_Compare(const void *ap, const void *bp)
7134 const entity_render_t *a = *(const entity_render_t **)ap;
7135 const entity_render_t *b = *(const entity_render_t **)bp;
7138 if(a->model < b->model)
7140 if(a->model > b->model)
7144 // TODO possibly calculate the REAL skinnum here first using
7146 if(a->skinnum < b->skinnum)
7148 if(a->skinnum > b->skinnum)
7151 // everything we compared is equal
7154 static void R_SortEntities(void)
7156 // below or equal 2 ents, sorting never gains anything
7157 if(r_refdef.scene.numentities <= 2)
7160 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7168 int dpsoftrast_test;
7169 extern cvar_t r_shadow_bouncegrid;
7170 void R_RenderView(void)
7172 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7174 rtexture_t *depthtexture;
7175 rtexture_t *colortexture;
7177 dpsoftrast_test = r_test.integer;
7179 if (r_timereport_active)
7180 R_TimeReport("start");
7181 r_textureframe++; // used only by R_GetCurrentTexture
7182 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7184 if(R_CompileShader_CheckStaticParms())
7187 if (!r_drawentities.integer)
7188 r_refdef.scene.numentities = 0;
7189 else if (r_sortentities.integer)
7192 R_AnimCache_ClearCache();
7194 /* adjust for stereo display */
7195 if(R_Stereo_Active())
7197 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);
7198 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7201 if (r_refdef.view.isoverlay)
7203 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7204 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7205 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7206 R_TimeReport("depthclear");
7208 r_refdef.view.showdebug = false;
7210 r_fb.water.enabled = false;
7211 r_fb.water.numwaterplanes = 0;
7213 R_RenderScene(0, NULL, NULL);
7215 r_refdef.view.matrix = originalmatrix;
7221 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7223 r_refdef.view.matrix = originalmatrix;
7227 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7229 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7230 // in sRGB fallback, behave similar to true sRGB: convert this
7231 // value from linear to sRGB
7232 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7234 R_RenderView_UpdateViewVectors();
7236 R_Shadow_UpdateWorldLightSelection();
7238 R_Bloom_StartFrame();
7240 // apply bloom brightness offset
7241 if(r_fb.bloomtexture[0])
7242 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7244 R_Water_StartFrame();
7246 // now we probably have an fbo to render into
7248 depthtexture = r_fb.depthtexture;
7249 colortexture = r_fb.colortexture;
7252 if (r_timereport_active)
7253 R_TimeReport("viewsetup");
7255 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7257 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7259 R_ClearScreen(r_refdef.fogenabled);
7260 if (r_timereport_active)
7261 R_TimeReport("viewclear");
7263 r_refdef.view.clear = true;
7265 r_refdef.view.showdebug = true;
7268 if (r_timereport_active)
7269 R_TimeReport("visibility");
7271 R_AnimCache_CacheVisibleEntities();
7272 if (r_timereport_active)
7273 R_TimeReport("animcache");
7275 R_Shadow_UpdateBounceGridTexture();
7276 if (r_timereport_active && r_shadow_bouncegrid.integer)
7277 R_TimeReport("bouncegrid");
7279 r_fb.water.numwaterplanes = 0;
7280 if (r_fb.water.enabled)
7281 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7283 R_RenderScene(fbo, depthtexture, colortexture);
7284 r_fb.water.numwaterplanes = 0;
7286 R_BlendView(fbo, depthtexture, colortexture);
7287 if (r_timereport_active)
7288 R_TimeReport("blendview");
7290 GL_Scissor(0, 0, vid.width, vid.height);
7291 GL_ScissorTest(false);
7293 r_refdef.view.matrix = originalmatrix;
7298 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7300 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7302 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7303 if (r_timereport_active)
7304 R_TimeReport("waterworld");
7307 // don't let sound skip if going slow
7308 if (r_refdef.scene.extraupdate)
7311 R_DrawModelsAddWaterPlanes();
7312 if (r_timereport_active)
7313 R_TimeReport("watermodels");
7315 if (r_fb.water.numwaterplanes)
7317 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7318 if (r_timereport_active)
7319 R_TimeReport("waterscenes");
7323 extern cvar_t cl_locs_show;
7324 static void R_DrawLocs(void);
7325 static void R_DrawEntityBBoxes(void);
7326 static void R_DrawModelDecals(void);
7327 extern cvar_t cl_decals_newsystem;
7328 extern qboolean r_shadow_usingdeferredprepass;
7329 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7331 qboolean shadowmapping = false;
7333 if (r_timereport_active)
7334 R_TimeReport("beginscene");
7336 r_refdef.stats[r_stat_renders]++;
7340 // don't let sound skip if going slow
7341 if (r_refdef.scene.extraupdate)
7344 R_MeshQueue_BeginScene();
7348 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);
7350 if (r_timereport_active)
7351 R_TimeReport("skystartframe");
7353 if (cl.csqc_vidvars.drawworld)
7355 // don't let sound skip if going slow
7356 if (r_refdef.scene.extraupdate)
7359 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7361 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7362 if (r_timereport_active)
7363 R_TimeReport("worldsky");
7366 if (R_DrawBrushModelsSky() && r_timereport_active)
7367 R_TimeReport("bmodelsky");
7369 if (skyrendermasked && skyrenderlater)
7371 // we have to force off the water clipping plane while rendering sky
7372 R_SetupView(false, fbo, depthtexture, colortexture);
7374 R_SetupView(true, fbo, depthtexture, colortexture);
7375 if (r_timereport_active)
7376 R_TimeReport("sky");
7380 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7381 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7382 R_Shadow_PrepareModelShadows();
7383 if (r_timereport_active)
7384 R_TimeReport("preparelights");
7386 if (R_Shadow_ShadowMappingEnabled())
7387 shadowmapping = true;
7389 if (r_shadow_usingdeferredprepass)
7390 R_Shadow_DrawPrepass();
7392 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7394 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7395 if (r_timereport_active)
7396 R_TimeReport("worlddepth");
7398 if (r_depthfirst.integer >= 2)
7400 R_DrawModelsDepth();
7401 if (r_timereport_active)
7402 R_TimeReport("modeldepth");
7405 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7407 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7408 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7409 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7410 // don't let sound skip if going slow
7411 if (r_refdef.scene.extraupdate)
7415 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7417 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7418 if (r_timereport_active)
7419 R_TimeReport("world");
7422 // don't let sound skip if going slow
7423 if (r_refdef.scene.extraupdate)
7427 if (r_timereport_active)
7428 R_TimeReport("models");
7430 // don't let sound skip if going slow
7431 if (r_refdef.scene.extraupdate)
7434 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7436 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7437 R_DrawModelShadows(fbo, depthtexture, colortexture);
7438 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7439 // don't let sound skip if going slow
7440 if (r_refdef.scene.extraupdate)
7444 if (!r_shadow_usingdeferredprepass)
7446 R_Shadow_DrawLights();
7447 if (r_timereport_active)
7448 R_TimeReport("rtlights");
7451 // don't let sound skip if going slow
7452 if (r_refdef.scene.extraupdate)
7455 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7457 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7458 R_DrawModelShadows(fbo, depthtexture, colortexture);
7459 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7460 // don't let sound skip if going slow
7461 if (r_refdef.scene.extraupdate)
7465 if (cl.csqc_vidvars.drawworld)
7467 if (cl_decals_newsystem.integer)
7469 R_DrawModelDecals();
7470 if (r_timereport_active)
7471 R_TimeReport("modeldecals");
7476 if (r_timereport_active)
7477 R_TimeReport("decals");
7481 if (r_timereport_active)
7482 R_TimeReport("particles");
7485 if (r_timereport_active)
7486 R_TimeReport("explosions");
7488 R_DrawLightningBeams();
7489 if (r_timereport_active)
7490 R_TimeReport("lightning");
7494 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7496 if (r_refdef.view.showdebug)
7498 if (cl_locs_show.integer)
7501 if (r_timereport_active)
7502 R_TimeReport("showlocs");
7505 if (r_drawportals.integer)
7508 if (r_timereport_active)
7509 R_TimeReport("portals");
7512 if (r_showbboxes.value > 0)
7514 R_DrawEntityBBoxes();
7515 if (r_timereport_active)
7516 R_TimeReport("bboxes");
7520 if (r_transparent.integer)
7522 R_MeshQueue_RenderTransparent();
7523 if (r_timereport_active)
7524 R_TimeReport("drawtrans");
7527 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))
7529 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7530 if (r_timereport_active)
7531 R_TimeReport("worlddebug");
7532 R_DrawModelsDebug();
7533 if (r_timereport_active)
7534 R_TimeReport("modeldebug");
7537 if (cl.csqc_vidvars.drawworld)
7539 R_Shadow_DrawCoronas();
7540 if (r_timereport_active)
7541 R_TimeReport("coronas");
7546 GL_DepthTest(false);
7547 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7548 GL_Color(1, 1, 1, 1);
7549 qglBegin(GL_POLYGON);
7550 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7551 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7552 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7553 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7555 qglBegin(GL_POLYGON);
7556 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]);
7557 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]);
7558 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]);
7559 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]);
7561 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7565 // don't let sound skip if going slow
7566 if (r_refdef.scene.extraupdate)
7570 static const unsigned short bboxelements[36] =
7580 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7583 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7585 RSurf_ActiveWorldEntity();
7587 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7588 GL_DepthMask(false);
7589 GL_DepthRange(0, 1);
7590 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7591 // R_Mesh_ResetTextureState();
7593 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7594 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7595 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7596 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7597 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7598 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7599 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7600 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7601 R_FillColors(color4f, 8, cr, cg, cb, ca);
7602 if (r_refdef.fogenabled)
7604 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7606 f1 = RSurf_FogVertex(v);
7608 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7609 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7610 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7613 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7614 R_Mesh_ResetTextureState();
7615 R_SetupShader_Generic_NoTexture(false, false);
7616 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7619 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7621 prvm_prog_t *prog = SVVM_prog;
7624 prvm_edict_t *edict;
7626 // this function draws bounding boxes of server entities
7630 GL_CullFace(GL_NONE);
7631 R_SetupShader_Generic_NoTexture(false, false);
7633 for (i = 0;i < numsurfaces;i++)
7635 edict = PRVM_EDICT_NUM(surfacelist[i]);
7636 switch ((int)PRVM_serveredictfloat(edict, solid))
7638 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7639 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7640 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7641 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7642 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7643 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7644 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7646 color[3] *= r_showbboxes.value;
7647 color[3] = bound(0, color[3], 1);
7648 GL_DepthTest(!r_showdisabledepthtest.integer);
7649 GL_CullFace(r_refdef.view.cullface_front);
7650 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7654 static void R_DrawEntityBBoxes(void)
7657 prvm_edict_t *edict;
7659 prvm_prog_t *prog = SVVM_prog;
7661 // this function draws bounding boxes of server entities
7665 for (i = 0;i < prog->num_edicts;i++)
7667 edict = PRVM_EDICT_NUM(i);
7668 if (edict->priv.server->free)
7670 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7671 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7673 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7675 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7676 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7680 static const int nomodelelement3i[24] =
7692 static const unsigned short nomodelelement3s[24] =
7704 static const float nomodelvertex3f[6*3] =
7714 static const float nomodelcolor4f[6*4] =
7716 0.0f, 0.0f, 0.5f, 1.0f,
7717 0.0f, 0.0f, 0.5f, 1.0f,
7718 0.0f, 0.5f, 0.0f, 1.0f,
7719 0.0f, 0.5f, 0.0f, 1.0f,
7720 0.5f, 0.0f, 0.0f, 1.0f,
7721 0.5f, 0.0f, 0.0f, 1.0f
7724 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7730 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);
7732 // this is only called once per entity so numsurfaces is always 1, and
7733 // surfacelist is always {0}, so this code does not handle batches
7735 if (rsurface.ent_flags & RENDER_ADDITIVE)
7737 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7738 GL_DepthMask(false);
7740 else if (rsurface.colormod[3] < 1)
7742 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7743 GL_DepthMask(false);
7747 GL_BlendFunc(GL_ONE, GL_ZERO);
7750 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7751 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7752 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7753 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7754 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7755 for (i = 0, c = color4f;i < 6;i++, c += 4)
7757 c[0] *= rsurface.colormod[0];
7758 c[1] *= rsurface.colormod[1];
7759 c[2] *= rsurface.colormod[2];
7760 c[3] *= rsurface.colormod[3];
7762 if (r_refdef.fogenabled)
7764 for (i = 0, c = color4f;i < 6;i++, c += 4)
7766 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7768 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7769 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7770 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7773 // R_Mesh_ResetTextureState();
7774 R_SetupShader_Generic_NoTexture(false, false);
7775 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7776 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7779 void R_DrawNoModel(entity_render_t *ent)
7782 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7783 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7784 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7786 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7789 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7791 vec3_t right1, right2, diff, normal;
7793 VectorSubtract (org2, org1, normal);
7795 // calculate 'right' vector for start
7796 VectorSubtract (r_refdef.view.origin, org1, diff);
7797 CrossProduct (normal, diff, right1);
7798 VectorNormalize (right1);
7800 // calculate 'right' vector for end
7801 VectorSubtract (r_refdef.view.origin, org2, diff);
7802 CrossProduct (normal, diff, right2);
7803 VectorNormalize (right2);
7805 vert[ 0] = org1[0] + width * right1[0];
7806 vert[ 1] = org1[1] + width * right1[1];
7807 vert[ 2] = org1[2] + width * right1[2];
7808 vert[ 3] = org1[0] - width * right1[0];
7809 vert[ 4] = org1[1] - width * right1[1];
7810 vert[ 5] = org1[2] - width * right1[2];
7811 vert[ 6] = org2[0] - width * right2[0];
7812 vert[ 7] = org2[1] - width * right2[1];
7813 vert[ 8] = org2[2] - width * right2[2];
7814 vert[ 9] = org2[0] + width * right2[0];
7815 vert[10] = org2[1] + width * right2[1];
7816 vert[11] = org2[2] + width * right2[2];
7819 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)
7821 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7822 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7823 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7824 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7825 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7826 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7827 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7828 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7829 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7830 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7831 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7832 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7835 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7840 VectorSet(v, x, y, z);
7841 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7842 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7844 if (i == mesh->numvertices)
7846 if (mesh->numvertices < mesh->maxvertices)
7848 VectorCopy(v, vertex3f);
7849 mesh->numvertices++;
7851 return mesh->numvertices;
7857 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7861 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7862 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7863 e = mesh->element3i + mesh->numtriangles * 3;
7864 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7866 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7867 if (mesh->numtriangles < mesh->maxtriangles)
7872 mesh->numtriangles++;
7874 element[1] = element[2];
7878 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7882 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7883 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7884 e = mesh->element3i + mesh->numtriangles * 3;
7885 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7887 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7888 if (mesh->numtriangles < mesh->maxtriangles)
7893 mesh->numtriangles++;
7895 element[1] = element[2];
7899 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7900 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7902 int planenum, planenum2;
7905 mplane_t *plane, *plane2;
7907 double temppoints[2][256*3];
7908 // figure out how large a bounding box we need to properly compute this brush
7910 for (w = 0;w < numplanes;w++)
7911 maxdist = max(maxdist, fabs(planes[w].dist));
7912 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7913 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7914 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7918 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7919 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7921 if (planenum2 == planenum)
7923 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);
7926 if (tempnumpoints < 3)
7928 // generate elements forming a triangle fan for this polygon
7929 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7933 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)
7935 texturelayer_t *layer;
7936 layer = t->currentlayers + t->currentnumlayers++;
7938 layer->depthmask = depthmask;
7939 layer->blendfunc1 = blendfunc1;
7940 layer->blendfunc2 = blendfunc2;
7941 layer->texture = texture;
7942 layer->texmatrix = *matrix;
7943 layer->color[0] = r;
7944 layer->color[1] = g;
7945 layer->color[2] = b;
7946 layer->color[3] = a;
7949 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7951 if(parms[0] == 0 && parms[1] == 0)
7953 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7954 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7959 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7962 index = parms[2] + rsurface.shadertime * parms[3];
7963 index -= floor(index);
7964 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7967 case Q3WAVEFUNC_NONE:
7968 case Q3WAVEFUNC_NOISE:
7969 case Q3WAVEFUNC_COUNT:
7972 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7973 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7974 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7975 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7976 case Q3WAVEFUNC_TRIANGLE:
7978 f = index - floor(index);
7991 f = parms[0] + parms[1] * f;
7992 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7993 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7997 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8003 matrix4x4_t matrix, temp;
8004 switch(tcmod->tcmod)
8008 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8009 matrix = r_waterscrollmatrix;
8011 matrix = identitymatrix;
8013 case Q3TCMOD_ENTITYTRANSLATE:
8014 // this is used in Q3 to allow the gamecode to control texcoord
8015 // scrolling on the entity, which is not supported in darkplaces yet.
8016 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8018 case Q3TCMOD_ROTATE:
8019 f = tcmod->parms[0] * rsurface.shadertime;
8020 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8021 Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
8022 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8025 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8027 case Q3TCMOD_SCROLL:
8028 // extra care is needed because of precision breakdown with large values of time
8029 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8030 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8031 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8033 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8034 w = (int) tcmod->parms[0];
8035 h = (int) tcmod->parms[1];
8036 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8038 idx = (int) floor(f * w * h);
8039 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8041 case Q3TCMOD_STRETCH:
8042 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8043 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8045 case Q3TCMOD_TRANSFORM:
8046 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8047 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8048 VectorSet(tcmat + 6, 0 , 0 , 1);
8049 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8050 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8052 case Q3TCMOD_TURBULENT:
8053 // this is handled in the RSurf_PrepareVertices function
8054 matrix = identitymatrix;
8058 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8061 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8063 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8064 char name[MAX_QPATH];
8065 skinframe_t *skinframe;
8066 unsigned char pixels[296*194];
8067 strlcpy(cache->name, skinname, sizeof(cache->name));
8068 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8069 if (developer_loading.integer)
8070 Con_Printf("loading %s\n", name);
8071 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8072 if (!skinframe || !skinframe->base)
8075 fs_offset_t filesize;
8077 f = FS_LoadFile(name, tempmempool, true, &filesize);
8080 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8081 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8085 cache->skinframe = skinframe;
8088 texture_t *R_GetCurrentTexture(texture_t *t)
8091 const entity_render_t *ent = rsurface.entity;
8092 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8093 q3shaderinfo_layer_tcmod_t *tcmod;
8095 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8096 return t->currentframe;
8097 t->update_lastrenderframe = r_textureframe;
8098 t->update_lastrenderentity = (void *)ent;
8100 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8101 t->camera_entity = ent->entitynumber;
8103 t->camera_entity = 0;
8105 // switch to an alternate material if this is a q1bsp animated material
8107 texture_t *texture = t;
8108 int s = rsurface.ent_skinnum;
8109 if ((unsigned int)s >= (unsigned int)model->numskins)
8111 if (model->skinscenes)
8113 if (model->skinscenes[s].framecount > 1)
8114 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8116 s = model->skinscenes[s].firstframe;
8119 t = t + s * model->num_surfaces;
8122 // use an alternate animation if the entity's frame is not 0,
8123 // and only if the texture has an alternate animation
8124 if (rsurface.ent_alttextures && t->anim_total[1])
8125 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8127 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8129 texture->currentframe = t;
8132 // update currentskinframe to be a qw skin or animation frame
8133 if (rsurface.ent_qwskin >= 0)
8135 i = rsurface.ent_qwskin;
8136 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8138 r_qwskincache_size = cl.maxclients;
8140 Mem_Free(r_qwskincache);
8141 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8143 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8144 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8145 t->currentskinframe = r_qwskincache[i].skinframe;
8146 if (t->currentskinframe == NULL)
8147 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8149 else if (t->numskinframes >= 2)
8150 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8151 if (t->backgroundnumskinframes >= 2)
8152 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8154 t->currentmaterialflags = t->basematerialflags;
8155 t->currentalpha = rsurface.colormod[3];
8156 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8157 t->currentalpha *= r_wateralpha.value;
8158 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8159 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8160 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8161 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8162 if (!(rsurface.ent_flags & RENDER_LIGHT))
8163 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8164 else if (FAKELIGHT_ENABLED)
8166 // no modellight if using fakelight for the map
8168 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8170 // pick a model lighting mode
8171 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8172 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8174 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8176 if (rsurface.ent_flags & RENDER_ADDITIVE)
8177 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8178 else if (t->currentalpha < 1)
8179 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8180 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8181 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8182 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8183 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8184 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8185 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8186 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8187 if (t->backgroundnumskinframes)
8188 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8189 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8191 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8192 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8195 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8196 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8198 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8199 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8201 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8202 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8204 // there is no tcmod
8205 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8207 t->currenttexmatrix = r_waterscrollmatrix;
8208 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8210 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8212 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8213 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8216 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8217 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8218 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8219 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8221 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8222 if (t->currentskinframe->qpixels)
8223 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8224 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8225 if (!t->basetexture)
8226 t->basetexture = r_texture_notexture;
8227 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8228 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8229 t->nmaptexture = t->currentskinframe->nmap;
8230 if (!t->nmaptexture)
8231 t->nmaptexture = r_texture_blanknormalmap;
8232 t->glosstexture = r_texture_black;
8233 t->glowtexture = t->currentskinframe->glow;
8234 t->fogtexture = t->currentskinframe->fog;
8235 t->reflectmasktexture = t->currentskinframe->reflect;
8236 if (t->backgroundnumskinframes)
8238 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8239 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8240 t->backgroundglosstexture = r_texture_black;
8241 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8242 if (!t->backgroundnmaptexture)
8243 t->backgroundnmaptexture = r_texture_blanknormalmap;
8244 // make sure that if glow is going to be used, both textures are not NULL
8245 if (!t->backgroundglowtexture && t->glowtexture)
8246 t->backgroundglowtexture = r_texture_black;
8247 if (!t->glowtexture && t->backgroundglowtexture)
8248 t->glowtexture = r_texture_black;
8252 t->backgroundbasetexture = r_texture_white;
8253 t->backgroundnmaptexture = r_texture_blanknormalmap;
8254 t->backgroundglosstexture = r_texture_black;
8255 t->backgroundglowtexture = NULL;
8257 t->specularpower = r_shadow_glossexponent.value;
8258 // TODO: store reference values for these in the texture?
8259 t->specularscale = 0;
8260 if (r_shadow_gloss.integer > 0)
8262 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8264 if (r_shadow_glossintensity.value > 0)
8266 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8267 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8268 t->specularscale = r_shadow_glossintensity.value;
8271 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8273 t->glosstexture = r_texture_white;
8274 t->backgroundglosstexture = r_texture_white;
8275 t->specularscale = r_shadow_gloss2intensity.value;
8276 t->specularpower = r_shadow_gloss2exponent.value;
8279 t->specularscale *= t->specularscalemod;
8280 t->specularpower *= t->specularpowermod;
8281 t->rtlightambient = 0;
8283 // lightmaps mode looks bad with dlights using actual texturing, so turn
8284 // off the colormap and glossmap, but leave the normalmap on as it still
8285 // accurately represents the shading involved
8286 if (gl_lightmaps.integer)
8288 t->basetexture = r_texture_grey128;
8289 t->pantstexture = r_texture_black;
8290 t->shirttexture = r_texture_black;
8291 if (gl_lightmaps.integer < 2)
8292 t->nmaptexture = r_texture_blanknormalmap;
8293 t->glosstexture = r_texture_black;
8294 t->glowtexture = NULL;
8295 t->fogtexture = NULL;
8296 t->reflectmasktexture = NULL;
8297 t->backgroundbasetexture = NULL;
8298 if (gl_lightmaps.integer < 2)
8299 t->backgroundnmaptexture = r_texture_blanknormalmap;
8300 t->backgroundglosstexture = r_texture_black;
8301 t->backgroundglowtexture = NULL;
8302 t->specularscale = 0;
8303 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8306 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8307 VectorClear(t->dlightcolor);
8308 t->currentnumlayers = 0;
8309 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8311 int blendfunc1, blendfunc2;
8313 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8315 blendfunc1 = GL_SRC_ALPHA;
8316 blendfunc2 = GL_ONE;
8318 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8320 blendfunc1 = GL_SRC_ALPHA;
8321 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8323 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8325 blendfunc1 = t->customblendfunc[0];
8326 blendfunc2 = t->customblendfunc[1];
8330 blendfunc1 = GL_ONE;
8331 blendfunc2 = GL_ZERO;
8333 // don't colormod evilblend textures
8334 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8335 VectorSet(t->lightmapcolor, 1, 1, 1);
8336 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8337 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8339 // fullbright is not affected by r_refdef.lightmapintensity
8340 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]);
8341 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8342 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]);
8343 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8344 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]);
8348 vec3_t ambientcolor;
8350 // set the color tint used for lights affecting this surface
8351 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8353 // q3bsp has no lightmap updates, so the lightstylevalue that
8354 // would normally be baked into the lightmap must be
8355 // applied to the color
8356 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8357 if (model->type == mod_brushq3)
8358 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8359 colorscale *= r_refdef.lightmapintensity;
8360 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8361 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8362 // basic lit geometry
8363 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]);
8364 // add pants/shirt if needed
8365 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8366 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]);
8367 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8368 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]);
8369 // now add ambient passes if needed
8370 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8372 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]);
8373 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8374 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]);
8375 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8376 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]);
8379 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8380 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]);
8381 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8383 // if this is opaque use alpha blend which will darken the earlier
8386 // if this is an alpha blended material, all the earlier passes
8387 // were darkened by fog already, so we only need to add the fog
8388 // color ontop through the fog mask texture
8390 // if this is an additive blended material, all the earlier passes
8391 // were darkened by fog already, and we should not add fog color
8392 // (because the background was not darkened, there is no fog color
8393 // that was lost behind it).
8394 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]);
8398 return t->currentframe;
8401 rsurfacestate_t rsurface;
8403 void RSurf_ActiveWorldEntity(void)
8405 dp_model_t *model = r_refdef.scene.worldmodel;
8406 //if (rsurface.entity == r_refdef.scene.worldentity)
8408 rsurface.entity = r_refdef.scene.worldentity;
8409 rsurface.skeleton = NULL;
8410 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8411 rsurface.ent_skinnum = 0;
8412 rsurface.ent_qwskin = -1;
8413 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8414 rsurface.shadertime = r_refdef.scene.time;
8415 rsurface.matrix = identitymatrix;
8416 rsurface.inversematrix = identitymatrix;
8417 rsurface.matrixscale = 1;
8418 rsurface.inversematrixscale = 1;
8419 R_EntityMatrix(&identitymatrix);
8420 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8421 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8422 rsurface.fograngerecip = r_refdef.fograngerecip;
8423 rsurface.fogheightfade = r_refdef.fogheightfade;
8424 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8425 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8426 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8427 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8428 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8429 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8430 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8431 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8432 rsurface.colormod[3] = 1;
8433 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);
8434 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8435 rsurface.frameblend[0].lerp = 1;
8436 rsurface.ent_alttextures = false;
8437 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8438 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8439 rsurface.entityskeletaltransform3x4 = NULL;
8440 rsurface.entityskeletaltransform3x4buffer = NULL;
8441 rsurface.entityskeletaltransform3x4offset = 0;
8442 rsurface.entityskeletaltransform3x4size = 0;;
8443 rsurface.entityskeletalnumtransforms = 0;
8444 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8445 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8446 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8447 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8448 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8449 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8450 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8451 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8452 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8453 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8454 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8455 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8456 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8457 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8458 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8459 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8460 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8461 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8462 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8463 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8464 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8465 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8466 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8467 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8468 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8469 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8470 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8471 rsurface.modelelement3i = model->surfmesh.data_element3i;
8472 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8473 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8474 rsurface.modelelement3s = model->surfmesh.data_element3s;
8475 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8476 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8477 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8478 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8479 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8480 rsurface.modelsurfaces = model->data_surfaces;
8481 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8482 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8484 rsurface.modelgeneratedvertex = false;
8485 rsurface.batchgeneratedvertex = false;
8486 rsurface.batchfirstvertex = 0;
8487 rsurface.batchnumvertices = 0;
8488 rsurface.batchfirsttriangle = 0;
8489 rsurface.batchnumtriangles = 0;
8490 rsurface.batchvertex3f = NULL;
8491 rsurface.batchvertex3f_vertexbuffer = NULL;
8492 rsurface.batchvertex3f_bufferoffset = 0;
8493 rsurface.batchsvector3f = NULL;
8494 rsurface.batchsvector3f_vertexbuffer = NULL;
8495 rsurface.batchsvector3f_bufferoffset = 0;
8496 rsurface.batchtvector3f = NULL;
8497 rsurface.batchtvector3f_vertexbuffer = NULL;
8498 rsurface.batchtvector3f_bufferoffset = 0;
8499 rsurface.batchnormal3f = NULL;
8500 rsurface.batchnormal3f_vertexbuffer = NULL;
8501 rsurface.batchnormal3f_bufferoffset = 0;
8502 rsurface.batchlightmapcolor4f = NULL;
8503 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8504 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8505 rsurface.batchtexcoordtexture2f = NULL;
8506 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8507 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8508 rsurface.batchtexcoordlightmap2f = NULL;
8509 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8510 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8511 rsurface.batchskeletalindex4ub = NULL;
8512 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8513 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8514 rsurface.batchskeletalweight4ub = NULL;
8515 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8516 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8517 rsurface.batchvertexmesh = NULL;
8518 rsurface.batchvertexmesh_vertexbuffer = NULL;
8519 rsurface.batchvertexmesh_bufferoffset = 0;
8520 rsurface.batchelement3i = NULL;
8521 rsurface.batchelement3i_indexbuffer = NULL;
8522 rsurface.batchelement3i_bufferoffset = 0;
8523 rsurface.batchelement3s = NULL;
8524 rsurface.batchelement3s_indexbuffer = NULL;
8525 rsurface.batchelement3s_bufferoffset = 0;
8526 rsurface.passcolor4f = NULL;
8527 rsurface.passcolor4f_vertexbuffer = NULL;
8528 rsurface.passcolor4f_bufferoffset = 0;
8529 rsurface.forcecurrenttextureupdate = false;
8532 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8534 dp_model_t *model = ent->model;
8535 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8537 rsurface.entity = (entity_render_t *)ent;
8538 rsurface.skeleton = ent->skeleton;
8539 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8540 rsurface.ent_skinnum = ent->skinnum;
8541 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;
8542 rsurface.ent_flags = ent->flags;
8543 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8544 rsurface.matrix = ent->matrix;
8545 rsurface.inversematrix = ent->inversematrix;
8546 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8547 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8548 R_EntityMatrix(&rsurface.matrix);
8549 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8550 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8551 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8552 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8553 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8554 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8555 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8556 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8557 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8558 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8559 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8560 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8561 rsurface.colormod[3] = ent->alpha;
8562 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8563 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8564 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8565 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8566 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8567 if (ent->model->brush.submodel && !prepass)
8569 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8570 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8572 // if the animcache code decided it should use the shader path, skip the deform step
8573 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8574 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8575 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8576 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8577 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8578 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8580 if (ent->animcache_vertex3f)
8582 r_refdef.stats[r_stat_batch_entitycache_count]++;
8583 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8584 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8585 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8586 rsurface.modelvertex3f = ent->animcache_vertex3f;
8587 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8588 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8589 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8590 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8591 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8592 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8593 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8594 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8595 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8596 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8597 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8598 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8599 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8600 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8602 else if (wanttangents)
8604 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8605 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8606 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8607 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8608 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8609 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8610 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8611 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8612 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8613 rsurface.modelvertexmesh = NULL;
8614 rsurface.modelvertexmesh_vertexbuffer = NULL;
8615 rsurface.modelvertexmesh_bufferoffset = 0;
8616 rsurface.modelvertex3f_vertexbuffer = NULL;
8617 rsurface.modelvertex3f_bufferoffset = 0;
8618 rsurface.modelvertex3f_vertexbuffer = 0;
8619 rsurface.modelvertex3f_bufferoffset = 0;
8620 rsurface.modelsvector3f_vertexbuffer = 0;
8621 rsurface.modelsvector3f_bufferoffset = 0;
8622 rsurface.modeltvector3f_vertexbuffer = 0;
8623 rsurface.modeltvector3f_bufferoffset = 0;
8624 rsurface.modelnormal3f_vertexbuffer = 0;
8625 rsurface.modelnormal3f_bufferoffset = 0;
8627 else if (wantnormals)
8629 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8630 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8631 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8632 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8633 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8634 rsurface.modelsvector3f = NULL;
8635 rsurface.modeltvector3f = NULL;
8636 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8637 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8638 rsurface.modelvertexmesh = NULL;
8639 rsurface.modelvertexmesh_vertexbuffer = NULL;
8640 rsurface.modelvertexmesh_bufferoffset = 0;
8641 rsurface.modelvertex3f_vertexbuffer = NULL;
8642 rsurface.modelvertex3f_bufferoffset = 0;
8643 rsurface.modelvertex3f_vertexbuffer = 0;
8644 rsurface.modelvertex3f_bufferoffset = 0;
8645 rsurface.modelsvector3f_vertexbuffer = 0;
8646 rsurface.modelsvector3f_bufferoffset = 0;
8647 rsurface.modeltvector3f_vertexbuffer = 0;
8648 rsurface.modeltvector3f_bufferoffset = 0;
8649 rsurface.modelnormal3f_vertexbuffer = 0;
8650 rsurface.modelnormal3f_bufferoffset = 0;
8654 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8655 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8656 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8657 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8658 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8659 rsurface.modelsvector3f = NULL;
8660 rsurface.modeltvector3f = NULL;
8661 rsurface.modelnormal3f = NULL;
8662 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8663 rsurface.modelvertexmesh = NULL;
8664 rsurface.modelvertexmesh_vertexbuffer = NULL;
8665 rsurface.modelvertexmesh_bufferoffset = 0;
8666 rsurface.modelvertex3f_vertexbuffer = NULL;
8667 rsurface.modelvertex3f_bufferoffset = 0;
8668 rsurface.modelvertex3f_vertexbuffer = 0;
8669 rsurface.modelvertex3f_bufferoffset = 0;
8670 rsurface.modelsvector3f_vertexbuffer = 0;
8671 rsurface.modelsvector3f_bufferoffset = 0;
8672 rsurface.modeltvector3f_vertexbuffer = 0;
8673 rsurface.modeltvector3f_bufferoffset = 0;
8674 rsurface.modelnormal3f_vertexbuffer = 0;
8675 rsurface.modelnormal3f_bufferoffset = 0;
8677 rsurface.modelgeneratedvertex = true;
8681 if (rsurface.entityskeletaltransform3x4)
8683 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8684 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8685 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8686 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8690 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8691 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8692 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8693 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8695 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8696 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8697 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8698 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8699 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8700 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8701 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8702 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8703 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8704 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8705 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8706 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8707 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8708 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8709 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8710 rsurface.modelgeneratedvertex = false;
8712 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8713 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8714 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8715 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8716 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8717 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8718 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8719 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8720 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8721 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8722 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8723 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8724 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8725 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8726 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8727 rsurface.modelelement3i = model->surfmesh.data_element3i;
8728 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8729 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8730 rsurface.modelelement3s = model->surfmesh.data_element3s;
8731 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8732 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8733 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8734 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8735 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8736 rsurface.modelsurfaces = model->data_surfaces;
8737 rsurface.batchgeneratedvertex = false;
8738 rsurface.batchfirstvertex = 0;
8739 rsurface.batchnumvertices = 0;
8740 rsurface.batchfirsttriangle = 0;
8741 rsurface.batchnumtriangles = 0;
8742 rsurface.batchvertex3f = NULL;
8743 rsurface.batchvertex3f_vertexbuffer = NULL;
8744 rsurface.batchvertex3f_bufferoffset = 0;
8745 rsurface.batchsvector3f = NULL;
8746 rsurface.batchsvector3f_vertexbuffer = NULL;
8747 rsurface.batchsvector3f_bufferoffset = 0;
8748 rsurface.batchtvector3f = NULL;
8749 rsurface.batchtvector3f_vertexbuffer = NULL;
8750 rsurface.batchtvector3f_bufferoffset = 0;
8751 rsurface.batchnormal3f = NULL;
8752 rsurface.batchnormal3f_vertexbuffer = NULL;
8753 rsurface.batchnormal3f_bufferoffset = 0;
8754 rsurface.batchlightmapcolor4f = NULL;
8755 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8756 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8757 rsurface.batchtexcoordtexture2f = NULL;
8758 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8759 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8760 rsurface.batchtexcoordlightmap2f = NULL;
8761 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8762 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8763 rsurface.batchskeletalindex4ub = NULL;
8764 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8765 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8766 rsurface.batchskeletalweight4ub = NULL;
8767 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8768 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8769 rsurface.batchvertexmesh = NULL;
8770 rsurface.batchvertexmesh_vertexbuffer = NULL;
8771 rsurface.batchvertexmesh_bufferoffset = 0;
8772 rsurface.batchelement3i = NULL;
8773 rsurface.batchelement3i_indexbuffer = NULL;
8774 rsurface.batchelement3i_bufferoffset = 0;
8775 rsurface.batchelement3s = NULL;
8776 rsurface.batchelement3s_indexbuffer = NULL;
8777 rsurface.batchelement3s_bufferoffset = 0;
8778 rsurface.passcolor4f = NULL;
8779 rsurface.passcolor4f_vertexbuffer = NULL;
8780 rsurface.passcolor4f_bufferoffset = 0;
8781 rsurface.forcecurrenttextureupdate = false;
8784 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)
8786 rsurface.entity = r_refdef.scene.worldentity;
8787 rsurface.skeleton = NULL;
8788 rsurface.ent_skinnum = 0;
8789 rsurface.ent_qwskin = -1;
8790 rsurface.ent_flags = entflags;
8791 rsurface.shadertime = r_refdef.scene.time - shadertime;
8792 rsurface.modelnumvertices = numvertices;
8793 rsurface.modelnumtriangles = numtriangles;
8794 rsurface.matrix = *matrix;
8795 rsurface.inversematrix = *inversematrix;
8796 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8797 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8798 R_EntityMatrix(&rsurface.matrix);
8799 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8800 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8801 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8802 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8803 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8804 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8805 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8806 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8807 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8808 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8809 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8810 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8811 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);
8812 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8813 rsurface.frameblend[0].lerp = 1;
8814 rsurface.ent_alttextures = false;
8815 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8816 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8817 rsurface.entityskeletaltransform3x4 = NULL;
8818 rsurface.entityskeletaltransform3x4buffer = NULL;
8819 rsurface.entityskeletaltransform3x4offset = 0;
8820 rsurface.entityskeletaltransform3x4size = 0;
8821 rsurface.entityskeletalnumtransforms = 0;
8822 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8823 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8824 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8825 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8828 rsurface.modelvertex3f = (float *)vertex3f;
8829 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8830 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8831 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8833 else if (wantnormals)
8835 rsurface.modelvertex3f = (float *)vertex3f;
8836 rsurface.modelsvector3f = NULL;
8837 rsurface.modeltvector3f = NULL;
8838 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8842 rsurface.modelvertex3f = (float *)vertex3f;
8843 rsurface.modelsvector3f = NULL;
8844 rsurface.modeltvector3f = NULL;
8845 rsurface.modelnormal3f = NULL;
8847 rsurface.modelvertexmesh = NULL;
8848 rsurface.modelvertexmesh_vertexbuffer = NULL;
8849 rsurface.modelvertexmesh_bufferoffset = 0;
8850 rsurface.modelvertex3f_vertexbuffer = 0;
8851 rsurface.modelvertex3f_bufferoffset = 0;
8852 rsurface.modelsvector3f_vertexbuffer = 0;
8853 rsurface.modelsvector3f_bufferoffset = 0;
8854 rsurface.modeltvector3f_vertexbuffer = 0;
8855 rsurface.modeltvector3f_bufferoffset = 0;
8856 rsurface.modelnormal3f_vertexbuffer = 0;
8857 rsurface.modelnormal3f_bufferoffset = 0;
8858 rsurface.modelgeneratedvertex = true;
8859 rsurface.modellightmapcolor4f = (float *)color4f;
8860 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8861 rsurface.modellightmapcolor4f_bufferoffset = 0;
8862 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8863 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8864 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8865 rsurface.modeltexcoordlightmap2f = NULL;
8866 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8867 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8868 rsurface.modelskeletalindex4ub = NULL;
8869 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8870 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8871 rsurface.modelskeletalweight4ub = NULL;
8872 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8873 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8874 rsurface.modelelement3i = (int *)element3i;
8875 rsurface.modelelement3i_indexbuffer = NULL;
8876 rsurface.modelelement3i_bufferoffset = 0;
8877 rsurface.modelelement3s = (unsigned short *)element3s;
8878 rsurface.modelelement3s_indexbuffer = NULL;
8879 rsurface.modelelement3s_bufferoffset = 0;
8880 rsurface.modellightmapoffsets = NULL;
8881 rsurface.modelsurfaces = NULL;
8882 rsurface.batchgeneratedvertex = false;
8883 rsurface.batchfirstvertex = 0;
8884 rsurface.batchnumvertices = 0;
8885 rsurface.batchfirsttriangle = 0;
8886 rsurface.batchnumtriangles = 0;
8887 rsurface.batchvertex3f = NULL;
8888 rsurface.batchvertex3f_vertexbuffer = NULL;
8889 rsurface.batchvertex3f_bufferoffset = 0;
8890 rsurface.batchsvector3f = NULL;
8891 rsurface.batchsvector3f_vertexbuffer = NULL;
8892 rsurface.batchsvector3f_bufferoffset = 0;
8893 rsurface.batchtvector3f = NULL;
8894 rsurface.batchtvector3f_vertexbuffer = NULL;
8895 rsurface.batchtvector3f_bufferoffset = 0;
8896 rsurface.batchnormal3f = NULL;
8897 rsurface.batchnormal3f_vertexbuffer = NULL;
8898 rsurface.batchnormal3f_bufferoffset = 0;
8899 rsurface.batchlightmapcolor4f = NULL;
8900 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8901 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8902 rsurface.batchtexcoordtexture2f = NULL;
8903 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8904 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8905 rsurface.batchtexcoordlightmap2f = NULL;
8906 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8907 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8908 rsurface.batchskeletalindex4ub = NULL;
8909 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8910 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8911 rsurface.batchskeletalweight4ub = NULL;
8912 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8913 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8914 rsurface.batchvertexmesh = NULL;
8915 rsurface.batchvertexmesh_vertexbuffer = NULL;
8916 rsurface.batchvertexmesh_bufferoffset = 0;
8917 rsurface.batchelement3i = NULL;
8918 rsurface.batchelement3i_indexbuffer = NULL;
8919 rsurface.batchelement3i_bufferoffset = 0;
8920 rsurface.batchelement3s = NULL;
8921 rsurface.batchelement3s_indexbuffer = NULL;
8922 rsurface.batchelement3s_bufferoffset = 0;
8923 rsurface.passcolor4f = NULL;
8924 rsurface.passcolor4f_vertexbuffer = NULL;
8925 rsurface.passcolor4f_bufferoffset = 0;
8926 rsurface.forcecurrenttextureupdate = true;
8928 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8930 if ((wantnormals || wanttangents) && !normal3f)
8932 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8933 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8935 if (wanttangents && !svector3f)
8937 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8938 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8939 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8944 float RSurf_FogPoint(const float *v)
8946 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8947 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8948 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8949 float FogHeightFade = r_refdef.fogheightfade;
8951 unsigned int fogmasktableindex;
8952 if (r_refdef.fogplaneviewabove)
8953 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8955 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8956 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8957 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8960 float RSurf_FogVertex(const float *v)
8962 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8963 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8964 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8965 float FogHeightFade = rsurface.fogheightfade;
8967 unsigned int fogmasktableindex;
8968 if (r_refdef.fogplaneviewabove)
8969 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8971 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8972 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8973 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8976 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8979 for (i = 0;i < numelements;i++)
8980 outelement3i[i] = inelement3i[i] + adjust;
8983 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8984 extern cvar_t gl_vbo;
8985 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8993 int surfacefirsttriangle;
8994 int surfacenumtriangles;
8995 int surfacefirstvertex;
8996 int surfaceendvertex;
8997 int surfacenumvertices;
8998 int batchnumsurfaces = texturenumsurfaces;
8999 int batchnumvertices;
9000 int batchnumtriangles;
9004 qboolean dynamicvertex;
9008 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9011 q3shaderinfo_deform_t *deform;
9012 const msurface_t *surface, *firstsurface;
9013 r_vertexmesh_t *vertexmesh;
9014 if (!texturenumsurfaces)
9016 // find vertex range of this surface batch
9018 firstsurface = texturesurfacelist[0];
9019 firsttriangle = firstsurface->num_firsttriangle;
9020 batchnumvertices = 0;
9021 batchnumtriangles = 0;
9022 firstvertex = endvertex = firstsurface->num_firstvertex;
9023 for (i = 0;i < texturenumsurfaces;i++)
9025 surface = texturesurfacelist[i];
9026 if (surface != firstsurface + i)
9028 surfacefirstvertex = surface->num_firstvertex;
9029 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9030 surfacenumvertices = surface->num_vertices;
9031 surfacenumtriangles = surface->num_triangles;
9032 if (firstvertex > surfacefirstvertex)
9033 firstvertex = surfacefirstvertex;
9034 if (endvertex < surfaceendvertex)
9035 endvertex = surfaceendvertex;
9036 batchnumvertices += surfacenumvertices;
9037 batchnumtriangles += surfacenumtriangles;
9040 r_refdef.stats[r_stat_batch_batches]++;
9042 r_refdef.stats[r_stat_batch_withgaps]++;
9043 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9044 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9045 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9047 // we now know the vertex range used, and if there are any gaps in it
9048 rsurface.batchfirstvertex = firstvertex;
9049 rsurface.batchnumvertices = endvertex - firstvertex;
9050 rsurface.batchfirsttriangle = firsttriangle;
9051 rsurface.batchnumtriangles = batchnumtriangles;
9053 // this variable holds flags for which properties have been updated that
9054 // may require regenerating vertexmesh array...
9057 // check if any dynamic vertex processing must occur
9058 dynamicvertex = false;
9060 // a cvar to force the dynamic vertex path to be taken, for debugging
9061 if (r_batch_debugdynamicvertexpath.integer)
9065 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9066 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9067 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9068 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9070 dynamicvertex = true;
9073 // if there is a chance of animated vertex colors, it's a dynamic batch
9074 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9078 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9079 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9080 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9081 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9083 dynamicvertex = true;
9084 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9087 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9089 switch (deform->deform)
9092 case Q3DEFORM_PROJECTIONSHADOW:
9093 case Q3DEFORM_TEXT0:
9094 case Q3DEFORM_TEXT1:
9095 case Q3DEFORM_TEXT2:
9096 case Q3DEFORM_TEXT3:
9097 case Q3DEFORM_TEXT4:
9098 case Q3DEFORM_TEXT5:
9099 case Q3DEFORM_TEXT6:
9100 case Q3DEFORM_TEXT7:
9103 case Q3DEFORM_AUTOSPRITE:
9106 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9107 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9108 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9109 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9111 dynamicvertex = true;
9112 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9113 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9115 case Q3DEFORM_AUTOSPRITE2:
9118 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9119 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9120 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9121 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9123 dynamicvertex = true;
9124 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9125 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9127 case Q3DEFORM_NORMAL:
9130 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9131 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9132 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9133 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9135 dynamicvertex = true;
9136 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9137 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9140 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9141 break; // if wavefunc is a nop, ignore this transform
9144 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9145 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9146 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9147 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9149 dynamicvertex = true;
9150 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9151 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9153 case Q3DEFORM_BULGE:
9156 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9157 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9158 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9159 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9161 dynamicvertex = true;
9162 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9163 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9166 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9167 break; // if wavefunc is a nop, ignore this transform
9170 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9171 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9172 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9173 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9175 dynamicvertex = true;
9176 batchneed |= BATCHNEED_ARRAY_VERTEX;
9177 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9181 switch(rsurface.texture->tcgen.tcgen)
9184 case Q3TCGEN_TEXTURE:
9186 case Q3TCGEN_LIGHTMAP:
9189 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9190 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9191 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9192 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9194 dynamicvertex = true;
9195 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9196 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9198 case Q3TCGEN_VECTOR:
9201 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9202 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9203 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9204 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9206 dynamicvertex = true;
9207 batchneed |= BATCHNEED_ARRAY_VERTEX;
9208 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9210 case Q3TCGEN_ENVIRONMENT:
9213 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9214 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9215 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9216 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9218 dynamicvertex = true;
9219 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9220 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9223 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9227 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9228 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9229 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9230 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9232 dynamicvertex = true;
9233 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9234 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9237 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9241 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9242 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9243 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9244 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9246 dynamicvertex = true;
9247 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9250 // when the model data has no vertex buffer (dynamic mesh), we need to
9252 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9253 batchneed |= BATCHNEED_NOGAPS;
9255 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9256 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9257 // we ensure this by treating the vertex batch as dynamic...
9258 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9262 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9263 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9264 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9265 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9267 dynamicvertex = true;
9272 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9273 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9274 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9275 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9276 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9277 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9278 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9279 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9282 // if needsupdate, we have to do a dynamic vertex batch for sure
9283 if (needsupdate & batchneed)
9287 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9288 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9289 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9290 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9292 dynamicvertex = true;
9295 // see if we need to build vertexmesh from arrays
9296 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9300 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9301 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9302 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9303 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9305 dynamicvertex = true;
9308 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9309 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9310 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9312 rsurface.batchvertex3f = rsurface.modelvertex3f;
9313 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9314 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9315 rsurface.batchsvector3f = rsurface.modelsvector3f;
9316 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9317 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9318 rsurface.batchtvector3f = rsurface.modeltvector3f;
9319 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9320 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9321 rsurface.batchnormal3f = rsurface.modelnormal3f;
9322 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9323 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9324 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9325 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9326 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9327 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9328 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9329 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9330 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9331 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9332 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9333 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9334 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9335 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9336 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9337 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9338 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9339 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9340 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9341 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9342 rsurface.batchelement3i = rsurface.modelelement3i;
9343 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9344 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9345 rsurface.batchelement3s = rsurface.modelelement3s;
9346 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9347 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9348 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9349 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9350 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9351 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9352 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9354 // if any dynamic vertex processing has to occur in software, we copy the
9355 // entire surface list together before processing to rebase the vertices
9356 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9358 // if any gaps exist and we do not have a static vertex buffer, we have to
9359 // copy the surface list together to avoid wasting upload bandwidth on the
9360 // vertices in the gaps.
9362 // if gaps exist and we have a static vertex buffer, we can choose whether
9363 // to combine the index buffer ranges into one dynamic index buffer or
9364 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9366 // in many cases the batch is reduced to one draw call.
9368 rsurface.batchmultidraw = false;
9369 rsurface.batchmultidrawnumsurfaces = 0;
9370 rsurface.batchmultidrawsurfacelist = NULL;
9374 // static vertex data, just set pointers...
9375 rsurface.batchgeneratedvertex = false;
9376 // if there are gaps, we want to build a combined index buffer,
9377 // otherwise use the original static buffer with an appropriate offset
9380 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9381 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9382 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9383 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9384 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9386 rsurface.batchmultidraw = true;
9387 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9388 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9391 // build a new triangle elements array for this batch
9392 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9393 rsurface.batchfirsttriangle = 0;
9395 for (i = 0;i < texturenumsurfaces;i++)
9397 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9398 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9399 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9400 numtriangles += surfacenumtriangles;
9402 rsurface.batchelement3i_indexbuffer = NULL;
9403 rsurface.batchelement3i_bufferoffset = 0;
9404 rsurface.batchelement3s = NULL;
9405 rsurface.batchelement3s_indexbuffer = NULL;
9406 rsurface.batchelement3s_bufferoffset = 0;
9407 if (endvertex <= 65536)
9409 // make a 16bit (unsigned short) index array if possible
9410 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9411 for (i = 0;i < numtriangles*3;i++)
9412 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9414 // upload buffer data for the copytriangles batch
9415 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9417 if (rsurface.batchelement3s)
9418 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9419 else if (rsurface.batchelement3i)
9420 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9425 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9426 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9427 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9428 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9433 // something needs software processing, do it for real...
9434 // we only directly handle separate array data in this case and then
9435 // generate interleaved data if needed...
9436 rsurface.batchgeneratedvertex = true;
9437 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9438 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9439 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9440 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9442 // now copy the vertex data into a combined array and make an index array
9443 // (this is what Quake3 does all the time)
9444 // we also apply any skeletal animation here that would have been done in
9445 // the vertex shader, because most of the dynamic vertex animation cases
9446 // need actual vertex positions and normals
9447 //if (dynamicvertex)
9449 rsurface.batchvertexmesh = NULL;
9450 rsurface.batchvertexmesh_vertexbuffer = NULL;
9451 rsurface.batchvertexmesh_bufferoffset = 0;
9452 rsurface.batchvertex3f = NULL;
9453 rsurface.batchvertex3f_vertexbuffer = NULL;
9454 rsurface.batchvertex3f_bufferoffset = 0;
9455 rsurface.batchsvector3f = NULL;
9456 rsurface.batchsvector3f_vertexbuffer = NULL;
9457 rsurface.batchsvector3f_bufferoffset = 0;
9458 rsurface.batchtvector3f = NULL;
9459 rsurface.batchtvector3f_vertexbuffer = NULL;
9460 rsurface.batchtvector3f_bufferoffset = 0;
9461 rsurface.batchnormal3f = NULL;
9462 rsurface.batchnormal3f_vertexbuffer = NULL;
9463 rsurface.batchnormal3f_bufferoffset = 0;
9464 rsurface.batchlightmapcolor4f = NULL;
9465 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9466 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9467 rsurface.batchtexcoordtexture2f = NULL;
9468 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9469 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9470 rsurface.batchtexcoordlightmap2f = NULL;
9471 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9472 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9473 rsurface.batchskeletalindex4ub = NULL;
9474 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9475 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9476 rsurface.batchskeletalweight4ub = NULL;
9477 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9478 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9479 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9480 rsurface.batchelement3i_indexbuffer = NULL;
9481 rsurface.batchelement3i_bufferoffset = 0;
9482 rsurface.batchelement3s = NULL;
9483 rsurface.batchelement3s_indexbuffer = NULL;
9484 rsurface.batchelement3s_bufferoffset = 0;
9485 rsurface.batchskeletaltransform3x4buffer = NULL;
9486 rsurface.batchskeletaltransform3x4offset = 0;
9487 rsurface.batchskeletaltransform3x4size = 0;
9488 // we'll only be setting up certain arrays as needed
9489 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9490 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9491 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9492 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9493 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9494 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9495 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9497 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9498 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9500 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9501 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9502 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9503 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9504 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9505 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9506 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9508 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9509 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9513 for (i = 0;i < texturenumsurfaces;i++)
9515 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9516 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9517 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9518 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9519 // copy only the data requested
9520 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9521 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9522 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9524 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9526 if (rsurface.batchvertex3f)
9527 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9529 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9531 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9533 if (rsurface.modelnormal3f)
9534 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9536 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9538 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9540 if (rsurface.modelsvector3f)
9542 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9543 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9547 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9548 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9551 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9553 if (rsurface.modellightmapcolor4f)
9554 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9556 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9558 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9560 if (rsurface.modeltexcoordtexture2f)
9561 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9563 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9565 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9567 if (rsurface.modeltexcoordlightmap2f)
9568 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9570 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9572 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9574 if (rsurface.modelskeletalindex4ub)
9576 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9577 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9581 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9582 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9583 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9584 for (j = 0;j < surfacenumvertices;j++)
9589 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9590 numvertices += surfacenumvertices;
9591 numtriangles += surfacenumtriangles;
9594 // generate a 16bit index array as well if possible
9595 // (in general, dynamic batches fit)
9596 if (numvertices <= 65536)
9598 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9599 for (i = 0;i < numtriangles*3;i++)
9600 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9603 // since we've copied everything, the batch now starts at 0
9604 rsurface.batchfirstvertex = 0;
9605 rsurface.batchnumvertices = batchnumvertices;
9606 rsurface.batchfirsttriangle = 0;
9607 rsurface.batchnumtriangles = batchnumtriangles;
9610 // apply skeletal animation that would have been done in the vertex shader
9611 if (rsurface.batchskeletaltransform3x4)
9613 const unsigned char *si;
9614 const unsigned char *sw;
9616 const float *b = rsurface.batchskeletaltransform3x4;
9617 float *vp, *vs, *vt, *vn;
9619 float m[3][4], n[3][4];
9620 float tp[3], ts[3], tt[3], tn[3];
9621 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9622 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9623 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9624 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9625 si = rsurface.batchskeletalindex4ub;
9626 sw = rsurface.batchskeletalweight4ub;
9627 vp = rsurface.batchvertex3f;
9628 vs = rsurface.batchsvector3f;
9629 vt = rsurface.batchtvector3f;
9630 vn = rsurface.batchnormal3f;
9631 memset(m[0], 0, sizeof(m));
9632 memset(n[0], 0, sizeof(n));
9633 for (i = 0;i < batchnumvertices;i++)
9635 t[0] = b + si[0]*12;
9638 // common case - only one matrix
9652 else if (sw[2] + sw[3])
9655 t[1] = b + si[1]*12;
9656 t[2] = b + si[2]*12;
9657 t[3] = b + si[3]*12;
9658 w[0] = sw[0] * (1.0f / 255.0f);
9659 w[1] = sw[1] * (1.0f / 255.0f);
9660 w[2] = sw[2] * (1.0f / 255.0f);
9661 w[3] = sw[3] * (1.0f / 255.0f);
9662 // blend the matrices
9663 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9664 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9665 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9666 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9667 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9668 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9669 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9670 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9671 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9672 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9673 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9674 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9679 t[1] = b + si[1]*12;
9680 w[0] = sw[0] * (1.0f / 255.0f);
9681 w[1] = sw[1] * (1.0f / 255.0f);
9682 // blend the matrices
9683 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9684 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9685 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9686 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9687 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9688 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9689 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9690 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9691 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9692 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9693 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9694 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9698 // modify the vertex
9700 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9701 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9702 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9706 // the normal transformation matrix is a set of cross products...
9707 CrossProduct(m[1], m[2], n[0]);
9708 CrossProduct(m[2], m[0], n[1]);
9709 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9711 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9712 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9713 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9714 VectorNormalize(vn);
9719 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9720 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9721 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9722 VectorNormalize(vs);
9725 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9726 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9727 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9728 VectorNormalize(vt);
9733 rsurface.batchskeletaltransform3x4 = NULL;
9734 rsurface.batchskeletalnumtransforms = 0;
9737 // q1bsp surfaces rendered in vertex color mode have to have colors
9738 // calculated based on lightstyles
9739 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9741 // generate color arrays for the surfaces in this list
9746 const unsigned char *lm;
9747 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9748 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9749 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9751 for (i = 0;i < texturenumsurfaces;i++)
9753 surface = texturesurfacelist[i];
9754 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9755 surfacenumvertices = surface->num_vertices;
9756 if (surface->lightmapinfo->samples)
9758 for (j = 0;j < surfacenumvertices;j++)
9760 lm = surface->lightmapinfo->samples + offsets[j];
9761 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9762 VectorScale(lm, scale, c);
9763 if (surface->lightmapinfo->styles[1] != 255)
9765 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9767 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9768 VectorMA(c, scale, lm, c);
9769 if (surface->lightmapinfo->styles[2] != 255)
9772 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9773 VectorMA(c, scale, lm, c);
9774 if (surface->lightmapinfo->styles[3] != 255)
9777 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9778 VectorMA(c, scale, lm, c);
9785 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);
9791 for (j = 0;j < surfacenumvertices;j++)
9793 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9800 // if vertices are deformed (sprite flares and things in maps, possibly
9801 // water waves, bulges and other deformations), modify the copied vertices
9803 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9805 switch (deform->deform)
9808 case Q3DEFORM_PROJECTIONSHADOW:
9809 case Q3DEFORM_TEXT0:
9810 case Q3DEFORM_TEXT1:
9811 case Q3DEFORM_TEXT2:
9812 case Q3DEFORM_TEXT3:
9813 case Q3DEFORM_TEXT4:
9814 case Q3DEFORM_TEXT5:
9815 case Q3DEFORM_TEXT6:
9816 case Q3DEFORM_TEXT7:
9819 case Q3DEFORM_AUTOSPRITE:
9820 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9821 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9822 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9823 VectorNormalize(newforward);
9824 VectorNormalize(newright);
9825 VectorNormalize(newup);
9826 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9827 // rsurface.batchvertex3f_vertexbuffer = NULL;
9828 // rsurface.batchvertex3f_bufferoffset = 0;
9829 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9830 // rsurface.batchsvector3f_vertexbuffer = NULL;
9831 // rsurface.batchsvector3f_bufferoffset = 0;
9832 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9833 // rsurface.batchtvector3f_vertexbuffer = NULL;
9834 // rsurface.batchtvector3f_bufferoffset = 0;
9835 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9836 // rsurface.batchnormal3f_vertexbuffer = NULL;
9837 // rsurface.batchnormal3f_bufferoffset = 0;
9838 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9839 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9840 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9841 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9842 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);
9843 // a single autosprite surface can contain multiple sprites...
9844 for (j = 0;j < batchnumvertices - 3;j += 4)
9846 VectorClear(center);
9847 for (i = 0;i < 4;i++)
9848 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9849 VectorScale(center, 0.25f, center);
9850 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9851 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9852 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9853 for (i = 0;i < 4;i++)
9855 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9856 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9859 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9860 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9861 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);
9863 case Q3DEFORM_AUTOSPRITE2:
9864 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9865 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9866 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9867 VectorNormalize(newforward);
9868 VectorNormalize(newright);
9869 VectorNormalize(newup);
9870 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9871 // rsurface.batchvertex3f_vertexbuffer = NULL;
9872 // rsurface.batchvertex3f_bufferoffset = 0;
9874 const float *v1, *v2;
9884 memset(shortest, 0, sizeof(shortest));
9885 // a single autosprite surface can contain multiple sprites...
9886 for (j = 0;j < batchnumvertices - 3;j += 4)
9888 VectorClear(center);
9889 for (i = 0;i < 4;i++)
9890 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9891 VectorScale(center, 0.25f, center);
9892 // find the two shortest edges, then use them to define the
9893 // axis vectors for rotating around the central axis
9894 for (i = 0;i < 6;i++)
9896 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9897 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9898 l = VectorDistance2(v1, v2);
9899 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9901 l += (1.0f / 1024.0f);
9902 if (shortest[0].length2 > l || i == 0)
9904 shortest[1] = shortest[0];
9905 shortest[0].length2 = l;
9906 shortest[0].v1 = v1;
9907 shortest[0].v2 = v2;
9909 else if (shortest[1].length2 > l || i == 1)
9911 shortest[1].length2 = l;
9912 shortest[1].v1 = v1;
9913 shortest[1].v2 = v2;
9916 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9917 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9918 // this calculates the right vector from the shortest edge
9919 // and the up vector from the edge midpoints
9920 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9921 VectorNormalize(right);
9922 VectorSubtract(end, start, up);
9923 VectorNormalize(up);
9924 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9925 VectorSubtract(rsurface.localvieworigin, center, forward);
9926 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9927 VectorNegate(forward, forward);
9928 VectorReflect(forward, 0, up, forward);
9929 VectorNormalize(forward);
9930 CrossProduct(up, forward, newright);
9931 VectorNormalize(newright);
9932 // rotate the quad around the up axis vector, this is made
9933 // especially easy by the fact we know the quad is flat,
9934 // so we only have to subtract the center position and
9935 // measure distance along the right vector, and then
9936 // multiply that by the newright vector and add back the
9938 // we also need to subtract the old position to undo the
9939 // displacement from the center, which we do with a
9940 // DotProduct, the subtraction/addition of center is also
9941 // optimized into DotProducts here
9942 l = DotProduct(right, center);
9943 for (i = 0;i < 4;i++)
9945 v1 = rsurface.batchvertex3f + 3*(j+i);
9946 f = DotProduct(right, v1) - l;
9947 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9951 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9953 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9954 // rsurface.batchnormal3f_vertexbuffer = NULL;
9955 // rsurface.batchnormal3f_bufferoffset = 0;
9956 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9958 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9960 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9961 // rsurface.batchsvector3f_vertexbuffer = NULL;
9962 // rsurface.batchsvector3f_bufferoffset = 0;
9963 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9964 // rsurface.batchtvector3f_vertexbuffer = NULL;
9965 // rsurface.batchtvector3f_bufferoffset = 0;
9966 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);
9969 case Q3DEFORM_NORMAL:
9970 // deform the normals to make reflections wavey
9971 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9972 rsurface.batchnormal3f_vertexbuffer = NULL;
9973 rsurface.batchnormal3f_bufferoffset = 0;
9974 for (j = 0;j < batchnumvertices;j++)
9977 float *normal = rsurface.batchnormal3f + 3*j;
9978 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9979 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9980 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9981 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9982 VectorNormalize(normal);
9984 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9986 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9987 // rsurface.batchsvector3f_vertexbuffer = NULL;
9988 // rsurface.batchsvector3f_bufferoffset = 0;
9989 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9990 // rsurface.batchtvector3f_vertexbuffer = NULL;
9991 // rsurface.batchtvector3f_bufferoffset = 0;
9992 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);
9996 // deform vertex array to make wavey water and flags and such
9997 waveparms[0] = deform->waveparms[0];
9998 waveparms[1] = deform->waveparms[1];
9999 waveparms[2] = deform->waveparms[2];
10000 waveparms[3] = deform->waveparms[3];
10001 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10002 break; // if wavefunc is a nop, don't make a dynamic vertex array
10003 // this is how a divisor of vertex influence on deformation
10004 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10005 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10006 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10007 // rsurface.batchvertex3f_vertexbuffer = NULL;
10008 // rsurface.batchvertex3f_bufferoffset = 0;
10009 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10010 // rsurface.batchnormal3f_vertexbuffer = NULL;
10011 // rsurface.batchnormal3f_bufferoffset = 0;
10012 for (j = 0;j < batchnumvertices;j++)
10014 // if the wavefunc depends on time, evaluate it per-vertex
10017 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10018 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10020 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10022 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10023 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10024 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10026 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10027 // rsurface.batchsvector3f_vertexbuffer = NULL;
10028 // rsurface.batchsvector3f_bufferoffset = 0;
10029 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10030 // rsurface.batchtvector3f_vertexbuffer = NULL;
10031 // rsurface.batchtvector3f_bufferoffset = 0;
10032 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);
10035 case Q3DEFORM_BULGE:
10036 // deform vertex array to make the surface have moving bulges
10037 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10038 // rsurface.batchvertex3f_vertexbuffer = NULL;
10039 // rsurface.batchvertex3f_bufferoffset = 0;
10040 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10041 // rsurface.batchnormal3f_vertexbuffer = NULL;
10042 // rsurface.batchnormal3f_bufferoffset = 0;
10043 for (j = 0;j < batchnumvertices;j++)
10045 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10046 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10048 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10049 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10050 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10052 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10053 // rsurface.batchsvector3f_vertexbuffer = NULL;
10054 // rsurface.batchsvector3f_bufferoffset = 0;
10055 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10056 // rsurface.batchtvector3f_vertexbuffer = NULL;
10057 // rsurface.batchtvector3f_bufferoffset = 0;
10058 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);
10061 case Q3DEFORM_MOVE:
10062 // deform vertex array
10063 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10064 break; // if wavefunc is a nop, don't make a dynamic vertex array
10065 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10066 VectorScale(deform->parms, scale, waveparms);
10067 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10068 // rsurface.batchvertex3f_vertexbuffer = NULL;
10069 // rsurface.batchvertex3f_bufferoffset = 0;
10070 for (j = 0;j < batchnumvertices;j++)
10071 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10076 // generate texcoords based on the chosen texcoord source
10077 switch(rsurface.texture->tcgen.tcgen)
10080 case Q3TCGEN_TEXTURE:
10082 case Q3TCGEN_LIGHTMAP:
10083 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10084 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10085 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10086 if (rsurface.batchtexcoordlightmap2f)
10087 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10089 case Q3TCGEN_VECTOR:
10090 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10091 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10092 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10093 for (j = 0;j < batchnumvertices;j++)
10095 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10096 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10099 case Q3TCGEN_ENVIRONMENT:
10100 // make environment reflections using a spheremap
10101 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10102 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10103 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10104 for (j = 0;j < batchnumvertices;j++)
10106 // identical to Q3A's method, but executed in worldspace so
10107 // carried models can be shiny too
10109 float viewer[3], d, reflected[3], worldreflected[3];
10111 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10112 // VectorNormalize(viewer);
10114 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10116 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10117 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10118 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10119 // note: this is proportinal to viewer, so we can normalize later
10121 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10122 VectorNormalize(worldreflected);
10124 // note: this sphere map only uses world x and z!
10125 // so positive and negative y will LOOK THE SAME.
10126 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10127 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10131 // the only tcmod that needs software vertex processing is turbulent, so
10132 // check for it here and apply the changes if needed
10133 // and we only support that as the first one
10134 // (handling a mixture of turbulent and other tcmods would be problematic
10135 // without punting it entirely to a software path)
10136 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10138 amplitude = rsurface.texture->tcmods[0].parms[1];
10139 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10140 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10141 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10142 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10143 for (j = 0;j < batchnumvertices;j++)
10145 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);
10146 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10150 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10152 // convert the modified arrays to vertex structs
10153 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10154 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10155 // rsurface.batchvertexmesh_bufferoffset = 0;
10156 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10157 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10158 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10159 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10160 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10161 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10162 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10164 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10166 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10167 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10170 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10171 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10172 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10173 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10174 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10175 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10176 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10177 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10178 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10179 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10181 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10183 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10184 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10189 // upload buffer data for the dynamic batch
10190 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10192 if (rsurface.batchvertexmesh)
10193 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10196 if (rsurface.batchvertex3f)
10197 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10198 if (rsurface.batchsvector3f)
10199 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10200 if (rsurface.batchtvector3f)
10201 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10202 if (rsurface.batchnormal3f)
10203 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10204 if (rsurface.batchlightmapcolor4f)
10205 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10206 if (rsurface.batchtexcoordtexture2f)
10207 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10208 if (rsurface.batchtexcoordlightmap2f)
10209 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10210 if (rsurface.batchskeletalindex4ub)
10211 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10212 if (rsurface.batchskeletalweight4ub)
10213 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10215 if (rsurface.batchelement3s)
10216 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10217 else if (rsurface.batchelement3i)
10218 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10222 void RSurf_DrawBatch(void)
10224 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10225 // through the pipeline, killing it earlier in the pipeline would have
10226 // per-surface overhead rather than per-batch overhead, so it's best to
10227 // reject it here, before it hits glDraw.
10228 if (rsurface.batchnumtriangles == 0)
10231 // batch debugging code
10232 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10238 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10239 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10242 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10244 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10246 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10247 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);
10254 if (rsurface.batchmultidraw)
10256 // issue multiple draws rather than copying index data
10257 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10258 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10259 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10260 for (i = 0;i < numsurfaces;)
10262 // combine consecutive surfaces as one draw
10263 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10264 if (surfacelist[j] != surfacelist[k] + 1)
10266 firstvertex = surfacelist[i]->num_firstvertex;
10267 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10268 firsttriangle = surfacelist[i]->num_firsttriangle;
10269 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10270 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);
10276 // there is only one consecutive run of index data (may have been combined)
10277 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);
10281 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10283 // pick the closest matching water plane
10284 int planeindex, vertexindex, bestplaneindex = -1;
10288 r_waterstate_waterplane_t *p;
10289 qboolean prepared = false;
10291 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10293 if(p->camera_entity != rsurface.texture->camera_entity)
10298 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10300 if(rsurface.batchnumvertices == 0)
10303 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10305 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10306 d += fabs(PlaneDiff(vert, &p->plane));
10308 if (bestd > d || bestplaneindex < 0)
10311 bestplaneindex = planeindex;
10314 return bestplaneindex;
10315 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10316 // this situation though, as it might be better to render single larger
10317 // batches with useless stuff (backface culled for example) than to
10318 // render multiple smaller batches
10321 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10324 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10325 rsurface.passcolor4f_vertexbuffer = 0;
10326 rsurface.passcolor4f_bufferoffset = 0;
10327 for (i = 0;i < rsurface.batchnumvertices;i++)
10328 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10331 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10338 if (rsurface.passcolor4f)
10340 // generate color arrays
10341 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10342 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10343 rsurface.passcolor4f_vertexbuffer = 0;
10344 rsurface.passcolor4f_bufferoffset = 0;
10345 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)
10347 f = RSurf_FogVertex(v);
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, c2 += 4)
10361 f = RSurf_FogVertex(v);
10370 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10377 if (!rsurface.passcolor4f)
10379 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10380 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10381 rsurface.passcolor4f_vertexbuffer = 0;
10382 rsurface.passcolor4f_bufferoffset = 0;
10383 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)
10385 f = RSurf_FogVertex(v);
10386 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10387 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10388 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10393 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10398 if (!rsurface.passcolor4f)
10400 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10401 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10402 rsurface.passcolor4f_vertexbuffer = 0;
10403 rsurface.passcolor4f_bufferoffset = 0;
10404 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10413 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10418 if (!rsurface.passcolor4f)
10420 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10421 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10422 rsurface.passcolor4f_vertexbuffer = 0;
10423 rsurface.passcolor4f_bufferoffset = 0;
10424 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10426 c2[0] = c[0] + r_refdef.scene.ambient;
10427 c2[1] = c[1] + r_refdef.scene.ambient;
10428 c2[2] = c[2] + r_refdef.scene.ambient;
10433 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10436 rsurface.passcolor4f = NULL;
10437 rsurface.passcolor4f_vertexbuffer = 0;
10438 rsurface.passcolor4f_bufferoffset = 0;
10439 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10440 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10441 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10442 GL_Color(r, g, b, a);
10443 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10444 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10445 R_Mesh_TexMatrix(0, NULL);
10449 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10451 // TODO: optimize applyfog && applycolor case
10452 // just apply fog if necessary, and tint the fog color array if necessary
10453 rsurface.passcolor4f = NULL;
10454 rsurface.passcolor4f_vertexbuffer = 0;
10455 rsurface.passcolor4f_bufferoffset = 0;
10456 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10457 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10458 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10459 GL_Color(r, g, b, a);
10463 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10466 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10467 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10468 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10469 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10470 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10471 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10472 GL_Color(r, g, b, a);
10476 static void RSurf_DrawBatch_GL11_ClampColor(void)
10481 if (!rsurface.passcolor4f)
10483 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10485 c2[0] = bound(0.0f, c1[0], 1.0f);
10486 c2[1] = bound(0.0f, c1[1], 1.0f);
10487 c2[2] = bound(0.0f, c1[2], 1.0f);
10488 c2[3] = bound(0.0f, c1[3], 1.0f);
10492 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10502 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10503 rsurface.passcolor4f_vertexbuffer = 0;
10504 rsurface.passcolor4f_bufferoffset = 0;
10505 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)
10507 f = -DotProduct(r_refdef.view.forward, n);
10509 f = f * 0.85 + 0.15; // work around so stuff won't get black
10510 f *= r_refdef.lightmapintensity;
10511 Vector4Set(c, f, f, f, 1);
10515 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10517 RSurf_DrawBatch_GL11_ApplyFakeLight();
10518 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10519 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10520 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10521 GL_Color(r, g, b, a);
10525 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10533 vec3_t ambientcolor;
10534 vec3_t diffusecolor;
10538 VectorCopy(rsurface.modellight_lightdir, lightdir);
10539 f = 0.5f * r_refdef.lightmapintensity;
10540 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10541 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10542 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10543 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10544 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10545 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10547 if (VectorLength2(diffusecolor) > 0)
10549 // q3-style directional shading
10550 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10551 rsurface.passcolor4f_vertexbuffer = 0;
10552 rsurface.passcolor4f_bufferoffset = 0;
10553 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)
10555 if ((f = DotProduct(n, lightdir)) > 0)
10556 VectorMA(ambientcolor, f, diffusecolor, c);
10558 VectorCopy(ambientcolor, c);
10565 *applycolor = false;
10569 *r = ambientcolor[0];
10570 *g = ambientcolor[1];
10571 *b = ambientcolor[2];
10572 rsurface.passcolor4f = NULL;
10573 rsurface.passcolor4f_vertexbuffer = 0;
10574 rsurface.passcolor4f_bufferoffset = 0;
10578 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10580 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10581 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10582 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10583 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10584 GL_Color(r, g, b, a);
10588 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10596 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10597 rsurface.passcolor4f_vertexbuffer = 0;
10598 rsurface.passcolor4f_bufferoffset = 0;
10600 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10602 f = 1 - RSurf_FogVertex(v);
10610 void RSurf_SetupDepthAndCulling(void)
10612 // submodels are biased to avoid z-fighting with world surfaces that they
10613 // may be exactly overlapping (avoids z-fighting artifacts on certain
10614 // doors and things in Quake maps)
10615 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10616 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10617 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10618 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10621 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10623 // transparent sky would be ridiculous
10624 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10626 R_SetupShader_Generic_NoTexture(false, false);
10627 skyrenderlater = true;
10628 RSurf_SetupDepthAndCulling();
10629 GL_DepthMask(true);
10630 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10631 // skymasking on them, and Quake3 never did sky masking (unlike
10632 // software Quake and software Quake2), so disable the sky masking
10633 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10634 // and skymasking also looks very bad when noclipping outside the
10635 // level, so don't use it then either.
10636 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10638 R_Mesh_ResetTextureState();
10639 if (skyrendermasked)
10641 R_SetupShader_DepthOrShadow(false, false, false);
10642 // depth-only (masking)
10643 GL_ColorMask(0,0,0,0);
10644 // just to make sure that braindead drivers don't draw
10645 // anything despite that colormask...
10646 GL_BlendFunc(GL_ZERO, GL_ONE);
10647 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10648 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10652 R_SetupShader_Generic_NoTexture(false, false);
10654 GL_BlendFunc(GL_ONE, GL_ZERO);
10655 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10656 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10657 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10660 if (skyrendermasked)
10661 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10663 R_Mesh_ResetTextureState();
10664 GL_Color(1, 1, 1, 1);
10667 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10668 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10669 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10671 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10675 // render screenspace normalmap to texture
10676 GL_DepthMask(true);
10677 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10682 // bind lightmap texture
10684 // water/refraction/reflection/camera surfaces have to be handled specially
10685 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10687 int start, end, startplaneindex;
10688 for (start = 0;start < texturenumsurfaces;start = end)
10690 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10691 if(startplaneindex < 0)
10693 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10694 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10698 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10700 // now that we have a batch using the same planeindex, render it
10701 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10703 // render water or distortion background
10704 GL_DepthMask(true);
10705 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);
10707 // blend surface on top
10708 GL_DepthMask(false);
10709 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10712 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10714 // render surface with reflection texture as input
10715 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10716 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);
10723 // render surface batch normally
10724 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10725 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);
10729 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10731 // OpenGL 1.3 path - anything not completely ancient
10732 qboolean applycolor;
10735 const texturelayer_t *layer;
10736 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);
10737 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10739 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10742 int layertexrgbscale;
10743 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10745 if (layerindex == 0)
10746 GL_AlphaTest(true);
10749 GL_AlphaTest(false);
10750 GL_DepthFunc(GL_EQUAL);
10753 GL_DepthMask(layer->depthmask && writedepth);
10754 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10755 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10757 layertexrgbscale = 4;
10758 VectorScale(layer->color, 0.25f, layercolor);
10760 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10762 layertexrgbscale = 2;
10763 VectorScale(layer->color, 0.5f, layercolor);
10767 layertexrgbscale = 1;
10768 VectorScale(layer->color, 1.0f, layercolor);
10770 layercolor[3] = layer->color[3];
10771 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10772 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10773 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10774 switch (layer->type)
10776 case TEXTURELAYERTYPE_LITTEXTURE:
10777 // single-pass lightmapped texture with 2x rgbscale
10778 R_Mesh_TexBind(0, r_texture_white);
10779 R_Mesh_TexMatrix(0, NULL);
10780 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10781 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10782 R_Mesh_TexBind(1, layer->texture);
10783 R_Mesh_TexMatrix(1, &layer->texmatrix);
10784 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10785 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10786 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10787 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10788 else if (FAKELIGHT_ENABLED)
10789 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10790 else if (rsurface.uselightmaptexture)
10791 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10793 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10795 case TEXTURELAYERTYPE_TEXTURE:
10796 // singletexture unlit texture with transparency support
10797 R_Mesh_TexBind(0, layer->texture);
10798 R_Mesh_TexMatrix(0, &layer->texmatrix);
10799 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10800 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10801 R_Mesh_TexBind(1, 0);
10802 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10803 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10805 case TEXTURELAYERTYPE_FOG:
10806 // singletexture fogging
10807 if (layer->texture)
10809 R_Mesh_TexBind(0, layer->texture);
10810 R_Mesh_TexMatrix(0, &layer->texmatrix);
10811 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10812 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10816 R_Mesh_TexBind(0, 0);
10817 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10819 R_Mesh_TexBind(1, 0);
10820 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10821 // generate a color array for the fog pass
10822 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10823 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10827 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10830 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10832 GL_DepthFunc(GL_LEQUAL);
10833 GL_AlphaTest(false);
10837 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10839 // OpenGL 1.1 - crusty old voodoo path
10842 const texturelayer_t *layer;
10843 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);
10844 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10846 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10848 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10850 if (layerindex == 0)
10851 GL_AlphaTest(true);
10854 GL_AlphaTest(false);
10855 GL_DepthFunc(GL_EQUAL);
10858 GL_DepthMask(layer->depthmask && writedepth);
10859 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10860 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10861 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10862 switch (layer->type)
10864 case TEXTURELAYERTYPE_LITTEXTURE:
10865 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10867 // two-pass lit texture with 2x rgbscale
10868 // first the lightmap pass
10869 R_Mesh_TexBind(0, r_texture_white);
10870 R_Mesh_TexMatrix(0, NULL);
10871 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10872 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10873 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10874 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10875 else if (FAKELIGHT_ENABLED)
10876 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10877 else if (rsurface.uselightmaptexture)
10878 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10880 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10881 // then apply the texture to it
10882 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10883 R_Mesh_TexBind(0, layer->texture);
10884 R_Mesh_TexMatrix(0, &layer->texmatrix);
10885 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10886 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10887 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);
10891 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10892 R_Mesh_TexBind(0, layer->texture);
10893 R_Mesh_TexMatrix(0, &layer->texmatrix);
10894 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10895 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10896 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10897 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);
10898 else if (FAKELIGHT_ENABLED)
10899 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);
10901 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);
10904 case TEXTURELAYERTYPE_TEXTURE:
10905 // singletexture unlit texture with 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 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);
10912 case TEXTURELAYERTYPE_FOG:
10913 // singletexture fogging
10914 if (layer->texture)
10916 R_Mesh_TexBind(0, layer->texture);
10917 R_Mesh_TexMatrix(0, &layer->texmatrix);
10918 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10919 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10923 R_Mesh_TexBind(0, 0);
10924 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10926 // generate a color array for the fog pass
10927 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10928 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10932 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10935 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10937 GL_DepthFunc(GL_LEQUAL);
10938 GL_AlphaTest(false);
10942 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10946 r_vertexgeneric_t *batchvertex;
10949 // R_Mesh_ResetTextureState();
10950 R_SetupShader_Generic_NoTexture(false, false);
10952 if(rsurface.texture && rsurface.texture->currentskinframe)
10954 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10955 c[3] *= rsurface.texture->currentalpha;
10965 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10967 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10968 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10969 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10972 // brighten it up (as texture value 127 means "unlit")
10973 c[0] *= 2 * r_refdef.view.colorscale;
10974 c[1] *= 2 * r_refdef.view.colorscale;
10975 c[2] *= 2 * r_refdef.view.colorscale;
10977 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10978 c[3] *= r_wateralpha.value;
10980 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10982 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10983 GL_DepthMask(false);
10985 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10987 GL_BlendFunc(GL_ONE, GL_ONE);
10988 GL_DepthMask(false);
10990 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10992 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10993 GL_DepthMask(false);
10995 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10997 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10998 GL_DepthMask(false);
11002 GL_BlendFunc(GL_ONE, GL_ZERO);
11003 GL_DepthMask(writedepth);
11006 if (r_showsurfaces.integer == 3)
11008 rsurface.passcolor4f = NULL;
11010 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11012 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11014 rsurface.passcolor4f = NULL;
11015 rsurface.passcolor4f_vertexbuffer = 0;
11016 rsurface.passcolor4f_bufferoffset = 0;
11018 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11020 qboolean applycolor = true;
11023 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11025 r_refdef.lightmapintensity = 1;
11026 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11027 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11029 else if (FAKELIGHT_ENABLED)
11031 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11033 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11034 RSurf_DrawBatch_GL11_ApplyFakeLight();
11035 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11039 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11041 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11042 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11043 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11046 if(!rsurface.passcolor4f)
11047 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11049 RSurf_DrawBatch_GL11_ApplyAmbient();
11050 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11051 if(r_refdef.fogenabled)
11052 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11053 RSurf_DrawBatch_GL11_ClampColor();
11055 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11056 R_SetupShader_Generic_NoTexture(false, false);
11059 else if (!r_refdef.view.showdebug)
11061 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11062 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11063 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11065 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11066 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11068 R_Mesh_PrepareVertices_Generic_Unlock();
11071 else if (r_showsurfaces.integer == 4)
11073 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11074 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11075 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11077 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11078 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11079 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11081 R_Mesh_PrepareVertices_Generic_Unlock();
11084 else if (r_showsurfaces.integer == 2)
11087 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11088 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11089 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11091 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11092 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11093 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11094 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11095 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11096 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11097 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11099 R_Mesh_PrepareVertices_Generic_Unlock();
11100 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11104 int texturesurfaceindex;
11106 const msurface_t *surface;
11107 float surfacecolor4f[4];
11108 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11109 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11111 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11113 surface = texturesurfacelist[texturesurfaceindex];
11114 k = (int)(((size_t)surface) / sizeof(msurface_t));
11115 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11116 for (j = 0;j < surface->num_vertices;j++)
11118 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11119 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11123 R_Mesh_PrepareVertices_Generic_Unlock();
11128 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11131 RSurf_SetupDepthAndCulling();
11132 if (r_showsurfaces.integer)
11134 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11137 switch (vid.renderpath)
11139 case RENDERPATH_GL20:
11140 case RENDERPATH_D3D9:
11141 case RENDERPATH_D3D10:
11142 case RENDERPATH_D3D11:
11143 case RENDERPATH_SOFT:
11144 case RENDERPATH_GLES2:
11145 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11147 case RENDERPATH_GL13:
11148 case RENDERPATH_GLES1:
11149 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11151 case RENDERPATH_GL11:
11152 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11158 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11161 RSurf_SetupDepthAndCulling();
11162 if (r_showsurfaces.integer)
11164 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11167 switch (vid.renderpath)
11169 case RENDERPATH_GL20:
11170 case RENDERPATH_D3D9:
11171 case RENDERPATH_D3D10:
11172 case RENDERPATH_D3D11:
11173 case RENDERPATH_SOFT:
11174 case RENDERPATH_GLES2:
11175 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11177 case RENDERPATH_GL13:
11178 case RENDERPATH_GLES1:
11179 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11181 case RENDERPATH_GL11:
11182 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11188 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11191 int texturenumsurfaces, endsurface;
11192 texture_t *texture;
11193 const msurface_t *surface;
11194 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11196 // if the model is static it doesn't matter what value we give for
11197 // wantnormals and wanttangents, so this logic uses only rules applicable
11198 // to a model, knowing that they are meaningless otherwise
11199 if (ent == r_refdef.scene.worldentity)
11200 RSurf_ActiveWorldEntity();
11201 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11202 RSurf_ActiveModelEntity(ent, false, false, false);
11205 switch (vid.renderpath)
11207 case RENDERPATH_GL20:
11208 case RENDERPATH_D3D9:
11209 case RENDERPATH_D3D10:
11210 case RENDERPATH_D3D11:
11211 case RENDERPATH_SOFT:
11212 case RENDERPATH_GLES2:
11213 RSurf_ActiveModelEntity(ent, true, true, false);
11215 case RENDERPATH_GL11:
11216 case RENDERPATH_GL13:
11217 case RENDERPATH_GLES1:
11218 RSurf_ActiveModelEntity(ent, true, false, false);
11223 if (r_transparentdepthmasking.integer)
11225 qboolean setup = false;
11226 for (i = 0;i < numsurfaces;i = j)
11229 surface = rsurface.modelsurfaces + surfacelist[i];
11230 texture = surface->texture;
11231 rsurface.texture = R_GetCurrentTexture(texture);
11232 rsurface.lightmaptexture = NULL;
11233 rsurface.deluxemaptexture = NULL;
11234 rsurface.uselightmaptexture = false;
11235 // scan ahead until we find a different texture
11236 endsurface = min(i + 1024, numsurfaces);
11237 texturenumsurfaces = 0;
11238 texturesurfacelist[texturenumsurfaces++] = surface;
11239 for (;j < endsurface;j++)
11241 surface = rsurface.modelsurfaces + surfacelist[j];
11242 if (texture != surface->texture)
11244 texturesurfacelist[texturenumsurfaces++] = surface;
11246 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11248 // render the range of surfaces as depth
11252 GL_ColorMask(0,0,0,0);
11254 GL_DepthTest(true);
11255 GL_BlendFunc(GL_ONE, GL_ZERO);
11256 GL_DepthMask(true);
11257 // R_Mesh_ResetTextureState();
11259 RSurf_SetupDepthAndCulling();
11260 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11261 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11262 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11266 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11269 for (i = 0;i < numsurfaces;i = j)
11272 surface = rsurface.modelsurfaces + surfacelist[i];
11273 texture = surface->texture;
11274 rsurface.texture = R_GetCurrentTexture(texture);
11275 // scan ahead until we find a different texture
11276 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11277 texturenumsurfaces = 0;
11278 texturesurfacelist[texturenumsurfaces++] = surface;
11279 if(FAKELIGHT_ENABLED)
11281 rsurface.lightmaptexture = NULL;
11282 rsurface.deluxemaptexture = NULL;
11283 rsurface.uselightmaptexture = false;
11284 for (;j < endsurface;j++)
11286 surface = rsurface.modelsurfaces + surfacelist[j];
11287 if (texture != surface->texture)
11289 texturesurfacelist[texturenumsurfaces++] = surface;
11294 rsurface.lightmaptexture = surface->lightmaptexture;
11295 rsurface.deluxemaptexture = surface->deluxemaptexture;
11296 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11297 for (;j < endsurface;j++)
11299 surface = rsurface.modelsurfaces + surfacelist[j];
11300 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11302 texturesurfacelist[texturenumsurfaces++] = surface;
11305 // render the range of surfaces
11306 if (ent == r_refdef.scene.worldentity)
11307 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11309 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11311 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11314 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11316 // transparent surfaces get pushed off into the transparent queue
11317 int surfacelistindex;
11318 const msurface_t *surface;
11319 vec3_t tempcenter, center;
11320 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11322 surface = texturesurfacelist[surfacelistindex];
11323 if (r_transparent_sortsurfacesbynearest.integer)
11325 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11326 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11327 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11331 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11332 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11333 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11335 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11336 if (rsurface.entity->transparent_offset) // transparent offset
11338 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11339 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11340 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11342 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);
11346 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11348 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11350 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11352 RSurf_SetupDepthAndCulling();
11353 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11354 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11355 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11359 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11363 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11366 if (!rsurface.texture->currentnumlayers)
11368 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11369 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11371 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11373 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11374 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11375 else if (!rsurface.texture->currentnumlayers)
11377 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11379 // in the deferred case, transparent surfaces were queued during prepass
11380 if (!r_shadow_usingdeferredprepass)
11381 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11385 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11386 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11391 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11394 texture_t *texture;
11395 R_FrameData_SetMark();
11396 // break the surface list down into batches by texture and use of lightmapping
11397 for (i = 0;i < numsurfaces;i = j)
11400 // texture is the base texture pointer, rsurface.texture is the
11401 // current frame/skin the texture is directing us to use (for example
11402 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11403 // use skin 1 instead)
11404 texture = surfacelist[i]->texture;
11405 rsurface.texture = R_GetCurrentTexture(texture);
11406 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11408 // if this texture is not the kind we want, skip ahead to the next one
11409 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11413 if(FAKELIGHT_ENABLED || depthonly || prepass)
11415 rsurface.lightmaptexture = NULL;
11416 rsurface.deluxemaptexture = NULL;
11417 rsurface.uselightmaptexture = false;
11418 // simply scan ahead until we find a different texture or lightmap state
11419 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11424 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11425 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11426 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11427 // simply scan ahead until we find a different texture or lightmap state
11428 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11431 // render the range of surfaces
11432 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11434 R_FrameData_ReturnToMark();
11437 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11441 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11444 if (!rsurface.texture->currentnumlayers)
11446 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11447 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11449 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11451 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11452 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11453 else if (!rsurface.texture->currentnumlayers)
11455 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11457 // in the deferred case, transparent surfaces were queued during prepass
11458 if (!r_shadow_usingdeferredprepass)
11459 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11463 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11464 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11469 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11472 texture_t *texture;
11473 R_FrameData_SetMark();
11474 // break the surface list down into batches by texture and use of lightmapping
11475 for (i = 0;i < numsurfaces;i = j)
11478 // texture is the base texture pointer, rsurface.texture is the
11479 // current frame/skin the texture is directing us to use (for example
11480 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11481 // use skin 1 instead)
11482 texture = surfacelist[i]->texture;
11483 rsurface.texture = R_GetCurrentTexture(texture);
11484 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11486 // if this texture is not the kind we want, skip ahead to the next one
11487 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11491 if(FAKELIGHT_ENABLED || depthonly || prepass)
11493 rsurface.lightmaptexture = NULL;
11494 rsurface.deluxemaptexture = NULL;
11495 rsurface.uselightmaptexture = false;
11496 // simply scan ahead until we find a different texture or lightmap state
11497 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11502 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11503 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11504 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11505 // simply scan ahead until we find a different texture or lightmap state
11506 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11509 // render the range of surfaces
11510 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11512 R_FrameData_ReturnToMark();
11515 float locboxvertex3f[6*4*3] =
11517 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11518 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11519 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11520 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11521 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11522 1,0,0, 0,0,0, 0,1,0, 1,1,0
11525 unsigned short locboxelements[6*2*3] =
11530 12,13,14, 12,14,15,
11531 16,17,18, 16,18,19,
11535 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11538 cl_locnode_t *loc = (cl_locnode_t *)ent;
11540 float vertex3f[6*4*3];
11542 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11543 GL_DepthMask(false);
11544 GL_DepthRange(0, 1);
11545 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11546 GL_DepthTest(true);
11547 GL_CullFace(GL_NONE);
11548 R_EntityMatrix(&identitymatrix);
11550 // R_Mesh_ResetTextureState();
11552 i = surfacelist[0];
11553 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11554 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11555 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11556 surfacelist[0] < 0 ? 0.5f : 0.125f);
11558 if (VectorCompare(loc->mins, loc->maxs))
11560 VectorSet(size, 2, 2, 2);
11561 VectorMA(loc->mins, -0.5f, size, mins);
11565 VectorCopy(loc->mins, mins);
11566 VectorSubtract(loc->maxs, loc->mins, size);
11569 for (i = 0;i < 6*4*3;)
11570 for (j = 0;j < 3;j++, i++)
11571 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11573 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11574 R_SetupShader_Generic_NoTexture(false, false);
11575 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11578 void R_DrawLocs(void)
11581 cl_locnode_t *loc, *nearestloc;
11583 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11584 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11586 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11587 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11591 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11593 if (decalsystem->decals)
11594 Mem_Free(decalsystem->decals);
11595 memset(decalsystem, 0, sizeof(*decalsystem));
11598 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)
11601 tridecal_t *decals;
11604 // expand or initialize the system
11605 if (decalsystem->maxdecals <= decalsystem->numdecals)
11607 decalsystem_t old = *decalsystem;
11608 qboolean useshortelements;
11609 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11610 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11611 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)));
11612 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11613 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11614 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11615 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11616 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11617 if (decalsystem->numdecals)
11618 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11620 Mem_Free(old.decals);
11621 for (i = 0;i < decalsystem->maxdecals*3;i++)
11622 decalsystem->element3i[i] = i;
11623 if (useshortelements)
11624 for (i = 0;i < decalsystem->maxdecals*3;i++)
11625 decalsystem->element3s[i] = i;
11628 // grab a decal and search for another free slot for the next one
11629 decals = decalsystem->decals;
11630 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11631 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11633 decalsystem->freedecal = i;
11634 if (decalsystem->numdecals <= i)
11635 decalsystem->numdecals = i + 1;
11637 // initialize the decal
11639 decal->triangleindex = triangleindex;
11640 decal->surfaceindex = surfaceindex;
11641 decal->decalsequence = decalsequence;
11642 decal->color4f[0][0] = c0[0];
11643 decal->color4f[0][1] = c0[1];
11644 decal->color4f[0][2] = c0[2];
11645 decal->color4f[0][3] = 1;
11646 decal->color4f[1][0] = c1[0];
11647 decal->color4f[1][1] = c1[1];
11648 decal->color4f[1][2] = c1[2];
11649 decal->color4f[1][3] = 1;
11650 decal->color4f[2][0] = c2[0];
11651 decal->color4f[2][1] = c2[1];
11652 decal->color4f[2][2] = c2[2];
11653 decal->color4f[2][3] = 1;
11654 decal->vertex3f[0][0] = v0[0];
11655 decal->vertex3f[0][1] = v0[1];
11656 decal->vertex3f[0][2] = v0[2];
11657 decal->vertex3f[1][0] = v1[0];
11658 decal->vertex3f[1][1] = v1[1];
11659 decal->vertex3f[1][2] = v1[2];
11660 decal->vertex3f[2][0] = v2[0];
11661 decal->vertex3f[2][1] = v2[1];
11662 decal->vertex3f[2][2] = v2[2];
11663 decal->texcoord2f[0][0] = t0[0];
11664 decal->texcoord2f[0][1] = t0[1];
11665 decal->texcoord2f[1][0] = t1[0];
11666 decal->texcoord2f[1][1] = t1[1];
11667 decal->texcoord2f[2][0] = t2[0];
11668 decal->texcoord2f[2][1] = t2[1];
11669 TriangleNormal(v0, v1, v2, decal->plane);
11670 VectorNormalize(decal->plane);
11671 decal->plane[3] = DotProduct(v0, decal->plane);
11674 extern cvar_t cl_decals_bias;
11675 extern cvar_t cl_decals_models;
11676 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11677 // baseparms, parms, temps
11678 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)
11683 const float *vertex3f;
11684 const float *normal3f;
11686 float points[2][9][3];
11693 e = rsurface.modelelement3i + 3*triangleindex;
11695 vertex3f = rsurface.modelvertex3f;
11696 normal3f = rsurface.modelnormal3f;
11700 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11702 index = 3*e[cornerindex];
11703 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11708 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11710 index = 3*e[cornerindex];
11711 VectorCopy(vertex3f + index, v[cornerindex]);
11716 //TriangleNormal(v[0], v[1], v[2], normal);
11717 //if (DotProduct(normal, localnormal) < 0.0f)
11719 // clip by each of the box planes formed from the projection matrix
11720 // if anything survives, we emit the decal
11721 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]);
11724 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]);
11727 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]);
11730 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]);
11733 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]);
11736 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]);
11739 // some part of the triangle survived, so we have to accept it...
11742 // dynamic always uses the original triangle
11744 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11746 index = 3*e[cornerindex];
11747 VectorCopy(vertex3f + index, v[cornerindex]);
11750 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11752 // convert vertex positions to texcoords
11753 Matrix4x4_Transform(projection, v[cornerindex], temp);
11754 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11755 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11756 // calculate distance fade from the projection origin
11757 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11758 f = bound(0.0f, f, 1.0f);
11759 c[cornerindex][0] = r * f;
11760 c[cornerindex][1] = g * f;
11761 c[cornerindex][2] = b * f;
11762 c[cornerindex][3] = 1.0f;
11763 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11766 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);
11768 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11769 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);
11771 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)
11773 matrix4x4_t projection;
11774 decalsystem_t *decalsystem;
11777 const msurface_t *surface;
11778 const msurface_t *surfaces;
11779 const int *surfacelist;
11780 const texture_t *texture;
11782 int numsurfacelist;
11783 int surfacelistindex;
11786 float localorigin[3];
11787 float localnormal[3];
11788 float localmins[3];
11789 float localmaxs[3];
11792 float planes[6][4];
11795 int bih_triangles_count;
11796 int bih_triangles[256];
11797 int bih_surfaces[256];
11799 decalsystem = &ent->decalsystem;
11800 model = ent->model;
11801 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11803 R_DecalSystem_Reset(&ent->decalsystem);
11807 if (!model->brush.data_leafs && !cl_decals_models.integer)
11809 if (decalsystem->model)
11810 R_DecalSystem_Reset(decalsystem);
11814 if (decalsystem->model != model)
11815 R_DecalSystem_Reset(decalsystem);
11816 decalsystem->model = model;
11818 RSurf_ActiveModelEntity(ent, true, false, false);
11820 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11821 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11822 VectorNormalize(localnormal);
11823 localsize = worldsize*rsurface.inversematrixscale;
11824 localmins[0] = localorigin[0] - localsize;
11825 localmins[1] = localorigin[1] - localsize;
11826 localmins[2] = localorigin[2] - localsize;
11827 localmaxs[0] = localorigin[0] + localsize;
11828 localmaxs[1] = localorigin[1] + localsize;
11829 localmaxs[2] = localorigin[2] + localsize;
11831 //VectorCopy(localnormal, planes[4]);
11832 //VectorVectors(planes[4], planes[2], planes[0]);
11833 AnglesFromVectors(angles, localnormal, NULL, false);
11834 AngleVectors(angles, planes[0], planes[2], planes[4]);
11835 VectorNegate(planes[0], planes[1]);
11836 VectorNegate(planes[2], planes[3]);
11837 VectorNegate(planes[4], planes[5]);
11838 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11839 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11840 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11841 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11842 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11843 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11848 matrix4x4_t forwardprojection;
11849 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11850 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11855 float projectionvector[4][3];
11856 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11857 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11858 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11859 projectionvector[0][0] = planes[0][0] * ilocalsize;
11860 projectionvector[0][1] = planes[1][0] * ilocalsize;
11861 projectionvector[0][2] = planes[2][0] * ilocalsize;
11862 projectionvector[1][0] = planes[0][1] * ilocalsize;
11863 projectionvector[1][1] = planes[1][1] * ilocalsize;
11864 projectionvector[1][2] = planes[2][1] * ilocalsize;
11865 projectionvector[2][0] = planes[0][2] * ilocalsize;
11866 projectionvector[2][1] = planes[1][2] * ilocalsize;
11867 projectionvector[2][2] = planes[2][2] * ilocalsize;
11868 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11869 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11870 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11871 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11875 dynamic = model->surfmesh.isanimated;
11876 numsurfacelist = model->nummodelsurfaces;
11877 surfacelist = model->sortedmodelsurfaces;
11878 surfaces = model->data_surfaces;
11881 bih_triangles_count = -1;
11884 if(model->render_bih.numleafs)
11885 bih = &model->render_bih;
11886 else if(model->collision_bih.numleafs)
11887 bih = &model->collision_bih;
11890 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11891 if(bih_triangles_count == 0)
11893 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11895 if(bih_triangles_count > 0)
11897 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11899 surfaceindex = bih_surfaces[triangleindex];
11900 surface = surfaces + surfaceindex;
11901 texture = surface->texture;
11902 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11904 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11906 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11911 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11913 surfaceindex = surfacelist[surfacelistindex];
11914 surface = surfaces + surfaceindex;
11915 // check cull box first because it rejects more than any other check
11916 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11918 // skip transparent surfaces
11919 texture = surface->texture;
11920 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11922 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11924 numtriangles = surface->num_triangles;
11925 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11926 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11931 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11932 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)
11934 int renderentityindex;
11935 float worldmins[3];
11936 float worldmaxs[3];
11937 entity_render_t *ent;
11939 if (!cl_decals_newsystem.integer)
11942 worldmins[0] = worldorigin[0] - worldsize;
11943 worldmins[1] = worldorigin[1] - worldsize;
11944 worldmins[2] = worldorigin[2] - worldsize;
11945 worldmaxs[0] = worldorigin[0] + worldsize;
11946 worldmaxs[1] = worldorigin[1] + worldsize;
11947 worldmaxs[2] = worldorigin[2] + worldsize;
11949 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11951 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11953 ent = r_refdef.scene.entities[renderentityindex];
11954 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11957 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11961 typedef struct r_decalsystem_splatqueue_s
11963 vec3_t worldorigin;
11964 vec3_t worldnormal;
11970 r_decalsystem_splatqueue_t;
11972 int r_decalsystem_numqueued = 0;
11973 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11975 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)
11977 r_decalsystem_splatqueue_t *queue;
11979 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11982 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11983 VectorCopy(worldorigin, queue->worldorigin);
11984 VectorCopy(worldnormal, queue->worldnormal);
11985 Vector4Set(queue->color, r, g, b, a);
11986 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11987 queue->worldsize = worldsize;
11988 queue->decalsequence = cl.decalsequence++;
11991 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11994 r_decalsystem_splatqueue_t *queue;
11996 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11997 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);
11998 r_decalsystem_numqueued = 0;
12001 extern cvar_t cl_decals_max;
12002 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12005 decalsystem_t *decalsystem = &ent->decalsystem;
12012 if (!decalsystem->numdecals)
12015 if (r_showsurfaces.integer)
12018 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12020 R_DecalSystem_Reset(decalsystem);
12024 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12025 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12027 if (decalsystem->lastupdatetime)
12028 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12031 decalsystem->lastupdatetime = r_refdef.scene.time;
12032 numdecals = decalsystem->numdecals;
12034 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12036 if (decal->color4f[0][3])
12038 decal->lived += frametime;
12039 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12041 memset(decal, 0, sizeof(*decal));
12042 if (decalsystem->freedecal > i)
12043 decalsystem->freedecal = i;
12047 decal = decalsystem->decals;
12048 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12051 // collapse the array by shuffling the tail decals into the gaps
12054 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12055 decalsystem->freedecal++;
12056 if (decalsystem->freedecal == numdecals)
12058 decal[decalsystem->freedecal] = decal[--numdecals];
12061 decalsystem->numdecals = numdecals;
12063 if (numdecals <= 0)
12065 // if there are no decals left, reset decalsystem
12066 R_DecalSystem_Reset(decalsystem);
12070 extern skinframe_t *decalskinframe;
12071 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12074 decalsystem_t *decalsystem = &ent->decalsystem;
12083 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12086 numdecals = decalsystem->numdecals;
12090 if (r_showsurfaces.integer)
12093 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12095 R_DecalSystem_Reset(decalsystem);
12099 // if the model is static it doesn't matter what value we give for
12100 // wantnormals and wanttangents, so this logic uses only rules applicable
12101 // to a model, knowing that they are meaningless otherwise
12102 if (ent == r_refdef.scene.worldentity)
12103 RSurf_ActiveWorldEntity();
12105 RSurf_ActiveModelEntity(ent, false, false, false);
12107 decalsystem->lastupdatetime = r_refdef.scene.time;
12109 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12111 // update vertex positions for animated models
12112 v3f = decalsystem->vertex3f;
12113 c4f = decalsystem->color4f;
12114 t2f = decalsystem->texcoord2f;
12115 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12117 if (!decal->color4f[0][3])
12120 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12124 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12127 // update color values for fading decals
12128 if (decal->lived >= cl_decals_time.value)
12129 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12133 c4f[ 0] = decal->color4f[0][0] * alpha;
12134 c4f[ 1] = decal->color4f[0][1] * alpha;
12135 c4f[ 2] = decal->color4f[0][2] * alpha;
12137 c4f[ 4] = decal->color4f[1][0] * alpha;
12138 c4f[ 5] = decal->color4f[1][1] * alpha;
12139 c4f[ 6] = decal->color4f[1][2] * alpha;
12141 c4f[ 8] = decal->color4f[2][0] * alpha;
12142 c4f[ 9] = decal->color4f[2][1] * alpha;
12143 c4f[10] = decal->color4f[2][2] * alpha;
12146 t2f[0] = decal->texcoord2f[0][0];
12147 t2f[1] = decal->texcoord2f[0][1];
12148 t2f[2] = decal->texcoord2f[1][0];
12149 t2f[3] = decal->texcoord2f[1][1];
12150 t2f[4] = decal->texcoord2f[2][0];
12151 t2f[5] = decal->texcoord2f[2][1];
12153 // update vertex positions for animated models
12154 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12156 e = rsurface.modelelement3i + 3*decal->triangleindex;
12157 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12158 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12159 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12163 VectorCopy(decal->vertex3f[0], v3f);
12164 VectorCopy(decal->vertex3f[1], v3f + 3);
12165 VectorCopy(decal->vertex3f[2], v3f + 6);
12168 if (r_refdef.fogenabled)
12170 alpha = RSurf_FogVertex(v3f);
12171 VectorScale(c4f, alpha, c4f);
12172 alpha = RSurf_FogVertex(v3f + 3);
12173 VectorScale(c4f + 4, alpha, c4f + 4);
12174 alpha = RSurf_FogVertex(v3f + 6);
12175 VectorScale(c4f + 8, alpha, c4f + 8);
12186 r_refdef.stats[r_stat_drawndecals] += numtris;
12188 // now render the decals all at once
12189 // (this assumes they all use one particle font texture!)
12190 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);
12191 // R_Mesh_ResetTextureState();
12192 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12193 GL_DepthMask(false);
12194 GL_DepthRange(0, 1);
12195 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12196 GL_DepthTest(true);
12197 GL_CullFace(GL_NONE);
12198 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12199 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12200 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12204 static void R_DrawModelDecals(void)
12208 // fade faster when there are too many decals
12209 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12210 for (i = 0;i < r_refdef.scene.numentities;i++)
12211 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12213 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12214 for (i = 0;i < r_refdef.scene.numentities;i++)
12215 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12216 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12218 R_DecalSystem_ApplySplatEntitiesQueue();
12220 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12221 for (i = 0;i < r_refdef.scene.numentities;i++)
12222 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12224 r_refdef.stats[r_stat_totaldecals] += numdecals;
12226 if (r_showsurfaces.integer)
12229 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12231 for (i = 0;i < r_refdef.scene.numentities;i++)
12233 if (!r_refdef.viewcache.entityvisible[i])
12235 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12236 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12240 extern cvar_t mod_collision_bih;
12241 static void R_DrawDebugModel(void)
12243 entity_render_t *ent = rsurface.entity;
12244 int i, j, flagsmask;
12245 const msurface_t *surface;
12246 dp_model_t *model = ent->model;
12248 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12251 if (r_showoverdraw.value > 0)
12253 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12254 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12255 R_SetupShader_Generic_NoTexture(false, false);
12256 GL_DepthTest(false);
12257 GL_DepthMask(false);
12258 GL_DepthRange(0, 1);
12259 GL_BlendFunc(GL_ONE, GL_ONE);
12260 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12262 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12264 rsurface.texture = R_GetCurrentTexture(surface->texture);
12265 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12267 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12268 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12269 if (!rsurface.texture->currentlayers->depthmask)
12270 GL_Color(c, 0, 0, 1.0f);
12271 else if (ent == r_refdef.scene.worldentity)
12272 GL_Color(c, c, c, 1.0f);
12274 GL_Color(0, c, 0, 1.0f);
12275 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12279 rsurface.texture = NULL;
12282 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12284 // R_Mesh_ResetTextureState();
12285 R_SetupShader_Generic_NoTexture(false, false);
12286 GL_DepthRange(0, 1);
12287 GL_DepthTest(!r_showdisabledepthtest.integer);
12288 GL_DepthMask(false);
12289 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12291 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12295 qboolean cullbox = false;
12296 const q3mbrush_t *brush;
12297 const bih_t *bih = &model->collision_bih;
12298 const bih_leaf_t *bihleaf;
12299 float vertex3f[3][3];
12300 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12301 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12303 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12305 switch (bihleaf->type)
12308 brush = model->brush.data_brushes + bihleaf->itemindex;
12309 if (brush->colbrushf && brush->colbrushf->numtriangles)
12311 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);
12312 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12313 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12316 case BIH_COLLISIONTRIANGLE:
12317 triangleindex = bihleaf->itemindex;
12318 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12319 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12320 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12321 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);
12322 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12323 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12325 case BIH_RENDERTRIANGLE:
12326 triangleindex = bihleaf->itemindex;
12327 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12328 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12329 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12330 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);
12331 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12332 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12338 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12341 if (r_showtris.integer && qglPolygonMode)
12343 if (r_showdisabledepthtest.integer)
12345 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12346 GL_DepthMask(false);
12350 GL_BlendFunc(GL_ONE, GL_ZERO);
12351 GL_DepthMask(true);
12353 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12354 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12356 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12358 rsurface.texture = R_GetCurrentTexture(surface->texture);
12359 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12361 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12362 if (!rsurface.texture->currentlayers->depthmask)
12363 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12364 else if (ent == r_refdef.scene.worldentity)
12365 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12367 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12368 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12372 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12373 rsurface.texture = NULL;
12376 if (r_shownormals.value != 0 && qglBegin)
12380 if (r_showdisabledepthtest.integer)
12382 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12383 GL_DepthMask(false);
12387 GL_BlendFunc(GL_ONE, GL_ZERO);
12388 GL_DepthMask(true);
12390 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12392 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12394 rsurface.texture = R_GetCurrentTexture(surface->texture);
12395 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12397 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12398 qglBegin(GL_LINES);
12399 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12401 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12403 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12404 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12405 qglVertex3f(v[0], v[1], v[2]);
12406 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12407 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12408 qglVertex3f(v[0], v[1], v[2]);
12411 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12413 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12415 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12416 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12417 qglVertex3f(v[0], v[1], v[2]);
12418 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12419 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12420 qglVertex3f(v[0], v[1], v[2]);
12423 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12425 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12427 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12428 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12429 qglVertex3f(v[0], v[1], v[2]);
12430 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12431 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12432 qglVertex3f(v[0], v[1], v[2]);
12435 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12437 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12439 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12440 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12441 qglVertex3f(v[0], v[1], v[2]);
12442 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12443 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12444 qglVertex3f(v[0], v[1], v[2]);
12451 rsurface.texture = NULL;
12456 int r_maxsurfacelist = 0;
12457 const msurface_t **r_surfacelist = NULL;
12458 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12460 int i, j, endj, flagsmask;
12461 dp_model_t *model = r_refdef.scene.worldmodel;
12462 msurface_t *surfaces;
12463 unsigned char *update;
12464 int numsurfacelist = 0;
12468 if (r_maxsurfacelist < model->num_surfaces)
12470 r_maxsurfacelist = model->num_surfaces;
12472 Mem_Free((msurface_t**)r_surfacelist);
12473 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12476 RSurf_ActiveWorldEntity();
12478 surfaces = model->data_surfaces;
12479 update = model->brushq1.lightmapupdateflags;
12481 // update light styles on this submodel
12482 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12484 model_brush_lightstyleinfo_t *style;
12485 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12487 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12489 int *list = style->surfacelist;
12490 style->value = r_refdef.scene.lightstylevalue[style->style];
12491 for (j = 0;j < style->numsurfaces;j++)
12492 update[list[j]] = true;
12497 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12501 R_DrawDebugModel();
12502 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12506 rsurface.lightmaptexture = NULL;
12507 rsurface.deluxemaptexture = NULL;
12508 rsurface.uselightmaptexture = false;
12509 rsurface.texture = NULL;
12510 rsurface.rtlight = NULL;
12511 numsurfacelist = 0;
12512 // add visible surfaces to draw list
12513 for (i = 0;i < model->nummodelsurfaces;i++)
12515 j = model->sortedmodelsurfaces[i];
12516 if (r_refdef.viewcache.world_surfacevisible[j])
12517 r_surfacelist[numsurfacelist++] = surfaces + j;
12519 // update lightmaps if needed
12520 if (model->brushq1.firstrender)
12522 model->brushq1.firstrender = false;
12523 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12525 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12529 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12530 if (r_refdef.viewcache.world_surfacevisible[j])
12532 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12534 // don't do anything if there were no surfaces
12535 if (!numsurfacelist)
12537 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12540 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12542 // add to stats if desired
12543 if (r_speeds.integer && !skysurfaces && !depthonly)
12545 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12546 for (j = 0;j < numsurfacelist;j++)
12547 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12550 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12553 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12555 int i, j, endj, flagsmask;
12556 dp_model_t *model = ent->model;
12557 msurface_t *surfaces;
12558 unsigned char *update;
12559 int numsurfacelist = 0;
12563 if (r_maxsurfacelist < model->num_surfaces)
12565 r_maxsurfacelist = model->num_surfaces;
12567 Mem_Free((msurface_t **)r_surfacelist);
12568 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12571 // if the model is static it doesn't matter what value we give for
12572 // wantnormals and wanttangents, so this logic uses only rules applicable
12573 // to a model, knowing that they are meaningless otherwise
12574 if (ent == r_refdef.scene.worldentity)
12575 RSurf_ActiveWorldEntity();
12576 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12577 RSurf_ActiveModelEntity(ent, false, false, false);
12579 RSurf_ActiveModelEntity(ent, true, true, true);
12580 else if (depthonly)
12582 switch (vid.renderpath)
12584 case RENDERPATH_GL20:
12585 case RENDERPATH_D3D9:
12586 case RENDERPATH_D3D10:
12587 case RENDERPATH_D3D11:
12588 case RENDERPATH_SOFT:
12589 case RENDERPATH_GLES2:
12590 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12592 case RENDERPATH_GL11:
12593 case RENDERPATH_GL13:
12594 case RENDERPATH_GLES1:
12595 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12601 switch (vid.renderpath)
12603 case RENDERPATH_GL20:
12604 case RENDERPATH_D3D9:
12605 case RENDERPATH_D3D10:
12606 case RENDERPATH_D3D11:
12607 case RENDERPATH_SOFT:
12608 case RENDERPATH_GLES2:
12609 RSurf_ActiveModelEntity(ent, true, true, false);
12611 case RENDERPATH_GL11:
12612 case RENDERPATH_GL13:
12613 case RENDERPATH_GLES1:
12614 RSurf_ActiveModelEntity(ent, true, false, false);
12619 surfaces = model->data_surfaces;
12620 update = model->brushq1.lightmapupdateflags;
12622 // update light styles
12623 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12625 model_brush_lightstyleinfo_t *style;
12626 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12628 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12630 int *list = style->surfacelist;
12631 style->value = r_refdef.scene.lightstylevalue[style->style];
12632 for (j = 0;j < style->numsurfaces;j++)
12633 update[list[j]] = true;
12638 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12642 R_DrawDebugModel();
12643 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12647 rsurface.lightmaptexture = NULL;
12648 rsurface.deluxemaptexture = NULL;
12649 rsurface.uselightmaptexture = false;
12650 rsurface.texture = NULL;
12651 rsurface.rtlight = NULL;
12652 numsurfacelist = 0;
12653 // add visible surfaces to draw list
12654 for (i = 0;i < model->nummodelsurfaces;i++)
12655 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12656 // don't do anything if there were no surfaces
12657 if (!numsurfacelist)
12659 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12662 // update lightmaps if needed
12666 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12671 R_BuildLightMap(ent, surfaces + j);
12676 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12678 // add to stats if desired
12679 if (r_speeds.integer && !skysurfaces && !depthonly)
12681 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12682 for (j = 0;j < numsurfacelist;j++)
12683 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12686 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12689 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12691 static texture_t texture;
12692 static msurface_t surface;
12693 const msurface_t *surfacelist = &surface;
12695 // fake enough texture and surface state to render this geometry
12697 texture.update_lastrenderframe = -1; // regenerate this texture
12698 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12699 texture.currentskinframe = skinframe;
12700 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12701 texture.offsetmapping = OFFSETMAPPING_OFF;
12702 texture.offsetscale = 1;
12703 texture.specularscalemod = 1;
12704 texture.specularpowermod = 1;
12705 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12706 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12707 // JUST GREP FOR "specularscalemod = 1".
12709 surface.texture = &texture;
12710 surface.num_triangles = numtriangles;
12711 surface.num_firsttriangle = firsttriangle;
12712 surface.num_vertices = numvertices;
12713 surface.num_firstvertex = firstvertex;
12716 rsurface.texture = R_GetCurrentTexture(surface.texture);
12717 rsurface.lightmaptexture = NULL;
12718 rsurface.deluxemaptexture = NULL;
12719 rsurface.uselightmaptexture = false;
12720 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12723 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)
12725 static msurface_t surface;
12726 const msurface_t *surfacelist = &surface;
12728 // fake enough texture and surface state to render this geometry
12729 surface.texture = texture;
12730 surface.num_triangles = numtriangles;
12731 surface.num_firsttriangle = firsttriangle;
12732 surface.num_vertices = numvertices;
12733 surface.num_firstvertex = firstvertex;
12736 rsurface.texture = R_GetCurrentTexture(surface.texture);
12737 rsurface.lightmaptexture = NULL;
12738 rsurface.deluxemaptexture = NULL;
12739 rsurface.uselightmaptexture = false;
12740 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);