2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47 static qboolean r_gpuskeletal;
54 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
55 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
61 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
62 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
63 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
64 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
65 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
73 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
81 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
82 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
85 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
92 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
93 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
102 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
127 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
138 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
149 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
150 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
156 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
157 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
158 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
162 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
163 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
172 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
175 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
178 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
179 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
180 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
181 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
182 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
183 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
184 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
186 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
187 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
188 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
189 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
190 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
191 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
192 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
193 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
194 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
196 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
197 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
198 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
199 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
201 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
202 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
204 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
205 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
206 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
207 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
208 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
209 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
211 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
212 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
213 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
214 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
215 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
218 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
219 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
220 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
222 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
224 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
226 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
228 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
230 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
231 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
232 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
235 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
236 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
238 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
240 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
241 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
243 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
244 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
245 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
246 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
249 extern cvar_t v_glslgamma;
250 extern cvar_t v_glslgamma_2d;
252 extern qboolean v_flipped_state;
254 r_framebufferstate_t r_fb;
256 /// shadow volume bsp struct with automatically growing nodes buffer
259 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
290 typedef struct r_qwskincache_s
292 char name[MAX_QPATH];
293 skinframe_t *skinframe;
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
310 const float r_d3dscreenvertex3f[12] =
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
321 for (i = 0;i < verts;i++)
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
335 for (i = 0;i < verts;i++)
345 // FIXME: move this to client?
348 if (gamemode == GAME_NEHAHRA)
350 Cvar_Set("gl_fogenable", "0");
351 Cvar_Set("gl_fogdensity", "0.2");
352 Cvar_Set("gl_fogred", "0.3");
353 Cvar_Set("gl_foggreen", "0.3");
354 Cvar_Set("gl_fogblue", "0.3");
356 r_refdef.fog_density = 0;
357 r_refdef.fog_red = 0;
358 r_refdef.fog_green = 0;
359 r_refdef.fog_blue = 0;
360 r_refdef.fog_alpha = 1;
361 r_refdef.fog_start = 0;
362 r_refdef.fog_end = 16384;
363 r_refdef.fog_height = 1<<30;
364 r_refdef.fog_fadedepth = 128;
365 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
368 static void R_BuildBlankTextures(void)
370 unsigned char data[4];
371 data[2] = 128; // normal X
372 data[1] = 128; // normal Y
373 data[0] = 255; // normal Z
374 data[3] = 255; // height
375 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 static void R_BuildNoTexture(void)
396 unsigned char pix[16][16][4];
397 // this makes a light grey/dark grey checkerboard texture
398 for (y = 0;y < 16;y++)
400 for (x = 0;x < 16;x++)
402 if ((y < 8) ^ (x < 8))
418 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
421 static void R_BuildWhiteCube(void)
423 unsigned char data[6*1*1*4];
424 memset(data, 255, sizeof(data));
425 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
428 static void R_BuildNormalizationCube(void)
432 vec_t s, t, intensity;
435 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436 for (side = 0;side < 6;side++)
438 for (y = 0;y < NORMSIZE;y++)
440 for (x = 0;x < NORMSIZE;x++)
442 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
478 intensity = 127.0f / sqrt(DotProduct(v, v));
479 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482 data[((side*64+y)*64+x)*4+3] = 255;
486 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
490 static void R_BuildFogTexture(void)
494 unsigned char data1[FOGWIDTH][4];
495 //unsigned char data2[FOGWIDTH][4];
498 r_refdef.fogmasktable_start = r_refdef.fog_start;
499 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500 r_refdef.fogmasktable_range = r_refdef.fogrange;
501 r_refdef.fogmasktable_density = r_refdef.fog_density;
503 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506 d = (x * r - r_refdef.fogmasktable_start);
507 if(developer_extra.integer)
508 Con_DPrintf("%f ", d);
510 if (r_fog_exp2.integer)
511 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514 if(developer_extra.integer)
515 Con_DPrintf(" : %f ", alpha);
516 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517 if(developer_extra.integer)
518 Con_DPrintf(" = %f\n", alpha);
519 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
522 for (x = 0;x < FOGWIDTH;x++)
524 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529 //data2[x][0] = 255 - b;
530 //data2[x][1] = 255 - b;
531 //data2[x][2] = 255 - b;
534 if (r_texture_fogattenuation)
536 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
546 static void R_BuildFogHeightTexture(void)
548 unsigned char *inpixels;
556 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557 if (r_refdef.fogheighttexturename[0])
558 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
561 r_refdef.fog_height_tablesize = 0;
562 if (r_texture_fogheighttexture)
563 R_FreeTexture(r_texture_fogheighttexture);
564 r_texture_fogheighttexture = NULL;
565 if (r_refdef.fog_height_table2d)
566 Mem_Free(r_refdef.fog_height_table2d);
567 r_refdef.fog_height_table2d = NULL;
568 if (r_refdef.fog_height_table1d)
569 Mem_Free(r_refdef.fog_height_table1d);
570 r_refdef.fog_height_table1d = NULL;
574 r_refdef.fog_height_tablesize = size;
575 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579 // LordHavoc: now the magic - what is that table2d for? it is a cooked
580 // average fog color table accounting for every fog layer between a point
581 // and the camera. (Note: attenuation is handled separately!)
582 for (y = 0;y < size;y++)
584 for (x = 0;x < size;x++)
590 for (j = x;j <= y;j++)
592 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
598 for (j = x;j >= y;j--)
600 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
611 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
614 //=======================================================================================================================================================
616 static const char *builtinshaderstrings[] =
618 #include "shader_glsl.h"
622 const char *builtinhlslshaderstrings[] =
624 #include "shader_hlsl.h"
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
631 //=======================================================================================================================================================
633 typedef struct shaderpermutationinfo_s
638 shaderpermutationinfo_t;
640 typedef struct shadermodeinfo_s
642 const char *filename;
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {"#define USEDIFFUSE\n", " diffuse"},
652 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653 {"#define USEVIEWTINT\n", " viewtint"},
654 {"#define USECOLORMAPPING\n", " colormapping"},
655 {"#define USESATURATION\n", " saturation"},
656 {"#define USEFOGINSIDE\n", " foginside"},
657 {"#define USEFOGOUTSIDE\n", " fogoutside"},
658 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660 {"#define USEGAMMARAMPS\n", " gammaramps"},
661 {"#define USECUBEFILTER\n", " cubefilter"},
662 {"#define USEGLOW\n", " glow"},
663 {"#define USEBLOOM\n", " bloom"},
664 {"#define USESPECULAR\n", " specular"},
665 {"#define USEPOSTPROCESSING\n", " postprocessing"},
666 {"#define USEREFLECTION\n", " reflection"},
667 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
671 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673 {"#define USEALPHAKILL\n", " alphakill"},
674 {"#define USEREFLECTCUBE\n", " reflectcube"},
675 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676 {"#define USEBOUNCEGRID\n", " bouncegrid"},
677 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
678 {"#define USETRIPPY\n", " trippy"},
679 {"#define USEDEPTHRGB\n", " depthrgb"},
680 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
681 {"#define USESKELETAL\n", " skeletal"}
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
687 {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688 {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689 {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690 {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691 {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692 {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693 {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
697 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
698 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
699 {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
700 {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
701 {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
702 {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703 {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
708 {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709 {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710 {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711 {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712 {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713 {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714 {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720 {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721 {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722 {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723 {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724 {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
727 struct r_glsl_permutation_s;
728 typedef struct r_glsl_permutation_s
731 struct r_glsl_permutation_s *hashnext;
733 unsigned int permutation;
735 /// indicates if we have tried compiling this permutation already
737 /// 0 if compilation failed
739 // texture units assigned to each detected uniform
740 int tex_Texture_First;
741 int tex_Texture_Second;
742 int tex_Texture_GammaRamps;
743 int tex_Texture_Normal;
744 int tex_Texture_Color;
745 int tex_Texture_Gloss;
746 int tex_Texture_Glow;
747 int tex_Texture_SecondaryNormal;
748 int tex_Texture_SecondaryColor;
749 int tex_Texture_SecondaryGloss;
750 int tex_Texture_SecondaryGlow;
751 int tex_Texture_Pants;
752 int tex_Texture_Shirt;
753 int tex_Texture_FogHeightTexture;
754 int tex_Texture_FogMask;
755 int tex_Texture_Lightmap;
756 int tex_Texture_Deluxemap;
757 int tex_Texture_Attenuation;
758 int tex_Texture_Cube;
759 int tex_Texture_Refraction;
760 int tex_Texture_Reflection;
761 int tex_Texture_ShadowMap2D;
762 int tex_Texture_CubeProjection;
763 int tex_Texture_ScreenNormalMap;
764 int tex_Texture_ScreenDiffuse;
765 int tex_Texture_ScreenSpecular;
766 int tex_Texture_ReflectMask;
767 int tex_Texture_ReflectCube;
768 int tex_Texture_BounceGrid;
769 /// locations of detected uniforms in program object, or -1 if not found
770 int loc_Texture_First;
771 int loc_Texture_Second;
772 int loc_Texture_GammaRamps;
773 int loc_Texture_Normal;
774 int loc_Texture_Color;
775 int loc_Texture_Gloss;
776 int loc_Texture_Glow;
777 int loc_Texture_SecondaryNormal;
778 int loc_Texture_SecondaryColor;
779 int loc_Texture_SecondaryGloss;
780 int loc_Texture_SecondaryGlow;
781 int loc_Texture_Pants;
782 int loc_Texture_Shirt;
783 int loc_Texture_FogHeightTexture;
784 int loc_Texture_FogMask;
785 int loc_Texture_Lightmap;
786 int loc_Texture_Deluxemap;
787 int loc_Texture_Attenuation;
788 int loc_Texture_Cube;
789 int loc_Texture_Refraction;
790 int loc_Texture_Reflection;
791 int loc_Texture_ShadowMap2D;
792 int loc_Texture_CubeProjection;
793 int loc_Texture_ScreenNormalMap;
794 int loc_Texture_ScreenDiffuse;
795 int loc_Texture_ScreenSpecular;
796 int loc_Texture_ReflectMask;
797 int loc_Texture_ReflectCube;
798 int loc_Texture_BounceGrid;
800 int loc_BloomBlur_Parameters;
802 int loc_Color_Ambient;
803 int loc_Color_Diffuse;
804 int loc_Color_Specular;
808 int loc_DeferredColor_Ambient;
809 int loc_DeferredColor_Diffuse;
810 int loc_DeferredColor_Specular;
811 int loc_DeferredMod_Diffuse;
812 int loc_DeferredMod_Specular;
813 int loc_DistortScaleRefractReflect;
816 int loc_FogHeightFade;
818 int loc_FogPlaneViewDist;
819 int loc_FogRangeRecip;
822 int loc_LightPosition;
823 int loc_OffsetMapping_ScaleSteps;
824 int loc_OffsetMapping_LodDistance;
825 int loc_OffsetMapping_Bias;
827 int loc_ReflectColor;
828 int loc_ReflectFactor;
829 int loc_ReflectOffset;
830 int loc_RefractColor;
832 int loc_ScreenCenterRefractReflect;
833 int loc_ScreenScaleRefractReflect;
834 int loc_ScreenToDepth;
835 int loc_ShadowMap_Parameters;
836 int loc_ShadowMap_TextureScale;
837 int loc_SpecularPower;
838 int loc_Skeletal_Transform12;
843 int loc_ViewTintColor;
845 int loc_ModelToLight;
847 int loc_BackgroundTexMatrix;
848 int loc_ModelViewProjectionMatrix;
849 int loc_ModelViewMatrix;
850 int loc_PixelToScreenTexCoord;
851 int loc_ModelToReflectCube;
852 int loc_ShadowMapMatrix;
853 int loc_BloomColorSubtract;
854 int loc_NormalmapScrollBlend;
855 int loc_BounceGridMatrix;
856 int loc_BounceGridIntensity;
857 /// uniform block bindings
858 int ubibind_Skeletal_Transform12_UniformBlock;
859 /// uniform block indices
860 int ubiloc_Skeletal_Transform12_UniformBlock;
862 r_glsl_permutation_t;
864 #define SHADERPERMUTATION_HASHSIZE 256
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
871 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
877 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
879 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
880 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
881 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
882 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
883 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
885 #define SHADERSTATICPARMS_COUNT 13
887 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
888 static int shaderstaticparms_count = 0;
890 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
891 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
893 extern qboolean r_shadow_shadowmapsampler;
894 extern int r_shadow_shadowmappcf;
895 qboolean R_CompileShader_CheckStaticParms(void)
897 static int r_compileshader_staticparms_save[1];
898 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
899 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
902 if (r_glsl_saturation_redcompensate.integer)
903 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
904 if (r_glsl_vertextextureblend_usebothalphas.integer)
905 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
906 if (r_shadow_glossexact.integer)
907 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
908 if (r_glsl_postprocess.integer)
910 if (r_glsl_postprocess_uservec1_enable.integer)
911 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
912 if (r_glsl_postprocess_uservec2_enable.integer)
913 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
914 if (r_glsl_postprocess_uservec3_enable.integer)
915 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
916 if (r_glsl_postprocess_uservec4_enable.integer)
917 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
919 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
920 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
922 if (r_shadow_shadowmapsampler)
923 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
924 if (r_shadow_shadowmappcf > 1)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
926 else if (r_shadow_shadowmappcf)
927 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
928 if (r_celshading.integer)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
930 if (r_celoutlines.integer)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
933 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
936 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
937 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
938 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
940 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
941 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
943 shaderstaticparms_count = 0;
946 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
947 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
948 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
949 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
950 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
951 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
952 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
953 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
954 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
955 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
956 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
957 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
958 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
961 /// information about each possible shader permutation
962 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
963 /// currently selected permutation
964 r_glsl_permutation_t *r_glsl_permutation;
965 /// storage for permutations linked in the hash table
966 memexpandablearray_t r_glsl_permutationarray;
968 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
970 //unsigned int hashdepth = 0;
971 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
972 r_glsl_permutation_t *p;
973 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
975 if (p->mode == mode && p->permutation == permutation)
977 //if (hashdepth > 10)
978 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
983 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
985 p->permutation = permutation;
986 p->hashnext = r_glsl_permutationhash[mode][hashindex];
987 r_glsl_permutationhash[mode][hashindex] = p;
988 //if (hashdepth > 10)
989 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
993 static char *R_ShaderStrCat(const char **strings)
996 const char **p = strings;
999 for (p = strings;(t = *p);p++)
1002 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1004 for (p = strings;(t = *p);p++)
1014 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1017 if (!filename || !filename[0])
1019 // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1020 if (!strcmp(filename, "glsl/default.glsl"))
1023 return R_ShaderStrCat(builtinshaderstrings);
1024 if (!glslshaderstring)
1026 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1027 if (glslshaderstring)
1028 Con_DPrintf("Loading shaders from file %s...\n", filename);
1030 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1032 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1033 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1034 return shaderstring;
1036 if (!strcmp(filename, "hlsl/default.hlsl"))
1039 return R_ShaderStrCat(builtinhlslshaderstrings);
1040 if (!hlslshaderstring)
1042 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1043 if (hlslshaderstring)
1044 Con_DPrintf("Loading shaders from file %s...\n", filename);
1046 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1048 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1049 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1050 return shaderstring;
1052 // we don't have builtin strings for any other files
1055 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1058 if (printfromdisknotice)
1059 Con_DPrintf("from disk %s... ", filename);
1060 return shaderstring;
1062 return shaderstring;
1065 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1070 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1072 char permutationname[256];
1073 int vertstrings_count = 0;
1074 int geomstrings_count = 0;
1075 int fragstrings_count = 0;
1076 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1077 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1078 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1085 permutationname[0] = 0;
1086 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1088 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1090 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1091 if(vid.support.glshaderversion >= 140)
1093 vertstrings_list[vertstrings_count++] = "#version 140\n";
1094 geomstrings_list[geomstrings_count++] = "#version 140\n";
1095 fragstrings_list[fragstrings_count++] = "#version 140\n";
1096 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1097 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1098 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1100 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1101 else if(vid.support.glshaderversion >= 130)
1103 vertstrings_list[vertstrings_count++] = "#version 130\n";
1104 geomstrings_list[geomstrings_count++] = "#version 130\n";
1105 fragstrings_list[fragstrings_count++] = "#version 130\n";
1106 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1107 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1108 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1111 // the first pretext is which type of shader to compile as
1112 // (later these will all be bound together as a program object)
1113 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1114 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1115 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1117 // the second pretext is the mode (for example a light source)
1118 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1119 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1120 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1121 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1123 // now add all the permutation pretexts
1124 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1126 if (permutation & (1<<i))
1128 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1129 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1130 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1131 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1135 // keep line numbers correct
1136 vertstrings_list[vertstrings_count++] = "\n";
1137 geomstrings_list[geomstrings_count++] = "\n";
1138 fragstrings_list[fragstrings_count++] = "\n";
1143 R_CompileShader_AddStaticParms(mode, permutation);
1144 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1145 vertstrings_count += shaderstaticparms_count;
1146 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1147 geomstrings_count += shaderstaticparms_count;
1148 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149 fragstrings_count += shaderstaticparms_count;
1151 // now append the shader text itself
1152 vertstrings_list[vertstrings_count++] = sourcestring;
1153 geomstrings_list[geomstrings_count++] = sourcestring;
1154 fragstrings_list[fragstrings_count++] = sourcestring;
1156 // compile the shader program
1157 if (vertstrings_count + geomstrings_count + fragstrings_count)
1158 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1162 qglUseProgram(p->program);CHECKGLERROR
1163 // look up all the uniform variable names we care about, so we don't
1164 // have to look them up every time we set them
1169 GLint activeuniformindex = 0;
1170 GLint numactiveuniforms = 0;
1171 char uniformname[128];
1172 GLsizei uniformnamelength = 0;
1173 GLint uniformsize = 0;
1174 GLenum uniformtype = 0;
1175 memset(uniformname, 0, sizeof(uniformname));
1176 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1177 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1178 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1180 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1181 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1186 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1187 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1188 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1189 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1190 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1191 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1192 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1193 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1194 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1195 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1196 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1197 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1198 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1199 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1200 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1201 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1202 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1203 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1204 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1205 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1206 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1207 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1208 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1209 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1210 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1211 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1212 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1213 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1214 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1215 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1216 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1217 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1218 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1219 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1220 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1221 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1222 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1223 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1224 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1225 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1226 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1227 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1228 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1229 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1230 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1231 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1232 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1233 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1234 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1235 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1236 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1237 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1238 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1239 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1240 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1241 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1242 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1243 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1244 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1245 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1246 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1247 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1248 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1249 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1250 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1251 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1252 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1253 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1254 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1255 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1256 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1257 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1258 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1259 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1260 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1261 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1262 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1263 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1264 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1265 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1266 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1267 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1268 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1269 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1270 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1271 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1272 // initialize the samplers to refer to the texture units we use
1273 p->tex_Texture_First = -1;
1274 p->tex_Texture_Second = -1;
1275 p->tex_Texture_GammaRamps = -1;
1276 p->tex_Texture_Normal = -1;
1277 p->tex_Texture_Color = -1;
1278 p->tex_Texture_Gloss = -1;
1279 p->tex_Texture_Glow = -1;
1280 p->tex_Texture_SecondaryNormal = -1;
1281 p->tex_Texture_SecondaryColor = -1;
1282 p->tex_Texture_SecondaryGloss = -1;
1283 p->tex_Texture_SecondaryGlow = -1;
1284 p->tex_Texture_Pants = -1;
1285 p->tex_Texture_Shirt = -1;
1286 p->tex_Texture_FogHeightTexture = -1;
1287 p->tex_Texture_FogMask = -1;
1288 p->tex_Texture_Lightmap = -1;
1289 p->tex_Texture_Deluxemap = -1;
1290 p->tex_Texture_Attenuation = -1;
1291 p->tex_Texture_Cube = -1;
1292 p->tex_Texture_Refraction = -1;
1293 p->tex_Texture_Reflection = -1;
1294 p->tex_Texture_ShadowMap2D = -1;
1295 p->tex_Texture_CubeProjection = -1;
1296 p->tex_Texture_ScreenNormalMap = -1;
1297 p->tex_Texture_ScreenDiffuse = -1;
1298 p->tex_Texture_ScreenSpecular = -1;
1299 p->tex_Texture_ReflectMask = -1;
1300 p->tex_Texture_ReflectCube = -1;
1301 p->tex_Texture_BounceGrid = -1;
1302 // bind the texture samplers in use
1304 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1305 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1306 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1307 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1308 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1309 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1310 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1311 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1312 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1313 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1314 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1315 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1316 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1317 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1318 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1319 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1320 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1321 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1322 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1323 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1324 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1325 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1326 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1327 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1328 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1329 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1330 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1331 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1332 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1333 // get the uniform block indices so we can bind them
1334 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1335 if (vid.support.arb_uniform_buffer_object)
1336 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1339 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1340 // clear the uniform block bindings
1341 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1342 // bind the uniform blocks in use
1344 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1345 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1347 // we're done compiling and setting up the shader, at least until it is used
1349 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1352 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1356 Mem_Free(sourcestring);
1359 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1361 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1362 if (r_glsl_permutation != perm)
1364 r_glsl_permutation = perm;
1365 if (!r_glsl_permutation->program)
1367 if (!r_glsl_permutation->compiled)
1369 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1370 R_GLSL_CompilePermutation(perm, mode, permutation);
1372 if (!r_glsl_permutation->program)
1374 // remove features until we find a valid permutation
1376 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1378 // reduce i more quickly whenever it would not remove any bits
1379 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1380 if (!(permutation & j))
1383 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1384 if (!r_glsl_permutation->compiled)
1385 R_GLSL_CompilePermutation(perm, mode, permutation);
1386 if (r_glsl_permutation->program)
1389 if (i >= SHADERPERMUTATION_COUNT)
1391 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1392 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1393 qglUseProgram(0);CHECKGLERROR
1394 return; // no bit left to clear, entire mode is broken
1399 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1401 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1402 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1403 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1411 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1412 extern D3DCAPS9 vid_d3d9caps;
1415 struct r_hlsl_permutation_s;
1416 typedef struct r_hlsl_permutation_s
1418 /// hash lookup data
1419 struct r_hlsl_permutation_s *hashnext;
1421 unsigned int permutation;
1423 /// indicates if we have tried compiling this permutation already
1425 /// NULL if compilation failed
1426 IDirect3DVertexShader9 *vertexshader;
1427 IDirect3DPixelShader9 *pixelshader;
1429 r_hlsl_permutation_t;
1431 typedef enum D3DVSREGISTER_e
1433 D3DVSREGISTER_TexMatrix = 0, // float4x4
1434 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1435 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1436 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1437 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1438 D3DVSREGISTER_ModelToLight = 20, // float4x4
1439 D3DVSREGISTER_EyePosition = 24,
1440 D3DVSREGISTER_FogPlane = 25,
1441 D3DVSREGISTER_LightDir = 26,
1442 D3DVSREGISTER_LightPosition = 27,
1446 typedef enum D3DPSREGISTER_e
1448 D3DPSREGISTER_Alpha = 0,
1449 D3DPSREGISTER_BloomBlur_Parameters = 1,
1450 D3DPSREGISTER_ClientTime = 2,
1451 D3DPSREGISTER_Color_Ambient = 3,
1452 D3DPSREGISTER_Color_Diffuse = 4,
1453 D3DPSREGISTER_Color_Specular = 5,
1454 D3DPSREGISTER_Color_Glow = 6,
1455 D3DPSREGISTER_Color_Pants = 7,
1456 D3DPSREGISTER_Color_Shirt = 8,
1457 D3DPSREGISTER_DeferredColor_Ambient = 9,
1458 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1459 D3DPSREGISTER_DeferredColor_Specular = 11,
1460 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1461 D3DPSREGISTER_DeferredMod_Specular = 13,
1462 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1463 D3DPSREGISTER_EyePosition = 15, // unused
1464 D3DPSREGISTER_FogColor = 16,
1465 D3DPSREGISTER_FogHeightFade = 17,
1466 D3DPSREGISTER_FogPlane = 18,
1467 D3DPSREGISTER_FogPlaneViewDist = 19,
1468 D3DPSREGISTER_FogRangeRecip = 20,
1469 D3DPSREGISTER_LightColor = 21,
1470 D3DPSREGISTER_LightDir = 22, // unused
1471 D3DPSREGISTER_LightPosition = 23,
1472 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1473 D3DPSREGISTER_PixelSize = 25,
1474 D3DPSREGISTER_ReflectColor = 26,
1475 D3DPSREGISTER_ReflectFactor = 27,
1476 D3DPSREGISTER_ReflectOffset = 28,
1477 D3DPSREGISTER_RefractColor = 29,
1478 D3DPSREGISTER_Saturation = 30,
1479 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1480 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1481 D3DPSREGISTER_ScreenToDepth = 33,
1482 D3DPSREGISTER_ShadowMap_Parameters = 34,
1483 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1484 D3DPSREGISTER_SpecularPower = 36,
1485 D3DPSREGISTER_UserVec1 = 37,
1486 D3DPSREGISTER_UserVec2 = 38,
1487 D3DPSREGISTER_UserVec3 = 39,
1488 D3DPSREGISTER_UserVec4 = 40,
1489 D3DPSREGISTER_ViewTintColor = 41,
1490 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1491 D3DPSREGISTER_BloomColorSubtract = 43,
1492 D3DPSREGISTER_ViewToLight = 44, // float4x4
1493 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1494 D3DPSREGISTER_NormalmapScrollBlend = 52,
1495 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1496 D3DPSREGISTER_OffsetMapping_Bias = 54,
1501 /// information about each possible shader permutation
1502 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1503 /// currently selected permutation
1504 r_hlsl_permutation_t *r_hlsl_permutation;
1505 /// storage for permutations linked in the hash table
1506 memexpandablearray_t r_hlsl_permutationarray;
1508 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1510 //unsigned int hashdepth = 0;
1511 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1512 r_hlsl_permutation_t *p;
1513 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1515 if (p->mode == mode && p->permutation == permutation)
1517 //if (hashdepth > 10)
1518 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1523 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1525 p->permutation = permutation;
1526 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1527 r_hlsl_permutationhash[mode][hashindex] = p;
1528 //if (hashdepth > 10)
1529 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1534 //#include <d3dx9shader.h>
1535 //#include <d3dx9mesh.h>
1537 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1539 DWORD *vsbin = NULL;
1540 DWORD *psbin = NULL;
1541 fs_offset_t vsbinsize;
1542 fs_offset_t psbinsize;
1543 // IDirect3DVertexShader9 *vs = NULL;
1544 // IDirect3DPixelShader9 *ps = NULL;
1545 ID3DXBuffer *vslog = NULL;
1546 ID3DXBuffer *vsbuffer = NULL;
1547 ID3DXConstantTable *vsconstanttable = NULL;
1548 ID3DXBuffer *pslog = NULL;
1549 ID3DXBuffer *psbuffer = NULL;
1550 ID3DXConstantTable *psconstanttable = NULL;
1553 char temp[MAX_INPUTLINE];
1554 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1556 qboolean debugshader = gl_paranoid.integer != 0;
1557 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1558 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1561 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1562 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1564 if ((!vsbin && vertstring) || (!psbin && fragstring))
1566 const char* dllnames_d3dx9 [] =
1590 dllhandle_t d3dx9_dll = NULL;
1591 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1592 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1593 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1594 dllfunction_t d3dx9_dllfuncs[] =
1596 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1597 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1598 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1601 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1602 #ifndef ID3DXBuffer_GetBufferPointer
1603 #if !defined(__cplusplus) || defined(CINTERFACE)
1604 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1605 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1606 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1608 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1609 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1610 #define ID3DXBuffer_Release(p) (p)->Release()
1613 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1615 DWORD shaderflags = 0;
1617 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1618 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1619 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1620 if (vertstring && vertstring[0])
1624 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1625 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1628 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1631 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1632 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1633 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1634 ID3DXBuffer_Release(vsbuffer);
1638 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1639 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1640 ID3DXBuffer_Release(vslog);
1643 if (fragstring && fragstring[0])
1647 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1648 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1651 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1654 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1655 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1656 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1657 ID3DXBuffer_Release(psbuffer);
1661 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1662 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1663 ID3DXBuffer_Release(pslog);
1666 Sys_UnloadLibrary(&d3dx9_dll);
1669 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1673 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1674 if (FAILED(vsresult))
1675 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1676 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1677 if (FAILED(psresult))
1678 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1680 // free the shader data
1681 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1682 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1685 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1688 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1689 int vertstring_length = 0;
1690 int geomstring_length = 0;
1691 int fragstring_length = 0;
1694 char *vertstring, *geomstring, *fragstring;
1695 char permutationname[256];
1696 char cachename[256];
1697 int vertstrings_count = 0;
1698 int geomstrings_count = 0;
1699 int fragstrings_count = 0;
1700 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1701 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1702 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1707 p->vertexshader = NULL;
1708 p->pixelshader = NULL;
1710 permutationname[0] = 0;
1712 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1714 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1715 strlcat(cachename, "hlsl/", sizeof(cachename));
1717 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1718 vertstrings_count = 0;
1719 geomstrings_count = 0;
1720 fragstrings_count = 0;
1721 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1722 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1723 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1725 // the first pretext is which type of shader to compile as
1726 // (later these will all be bound together as a program object)
1727 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1728 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1729 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1731 // the second pretext is the mode (for example a light source)
1732 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1733 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1734 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1735 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1736 strlcat(cachename, modeinfo->name, sizeof(cachename));
1738 // now add all the permutation pretexts
1739 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1741 if (permutation & (1<<i))
1743 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1744 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1745 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1746 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1747 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1751 // keep line numbers correct
1752 vertstrings_list[vertstrings_count++] = "\n";
1753 geomstrings_list[geomstrings_count++] = "\n";
1754 fragstrings_list[fragstrings_count++] = "\n";
1759 R_CompileShader_AddStaticParms(mode, permutation);
1760 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1761 vertstrings_count += shaderstaticparms_count;
1762 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1763 geomstrings_count += shaderstaticparms_count;
1764 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1765 fragstrings_count += shaderstaticparms_count;
1767 // replace spaces in the cachename with _ characters
1768 for (i = 0;cachename[i];i++)
1769 if (cachename[i] == ' ')
1772 // now append the shader text itself
1773 vertstrings_list[vertstrings_count++] = sourcestring;
1774 geomstrings_list[geomstrings_count++] = sourcestring;
1775 fragstrings_list[fragstrings_count++] = sourcestring;
1777 vertstring_length = 0;
1778 for (i = 0;i < vertstrings_count;i++)
1779 vertstring_length += strlen(vertstrings_list[i]);
1780 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1781 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1782 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1784 geomstring_length = 0;
1785 for (i = 0;i < geomstrings_count;i++)
1786 geomstring_length += strlen(geomstrings_list[i]);
1787 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1788 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1789 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1791 fragstring_length = 0;
1792 for (i = 0;i < fragstrings_count;i++)
1793 fragstring_length += strlen(fragstrings_list[i]);
1794 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1795 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1796 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1798 // try to load the cached shader, or generate one
1799 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1801 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1802 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1804 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1808 Mem_Free(vertstring);
1810 Mem_Free(geomstring);
1812 Mem_Free(fragstring);
1814 Mem_Free(sourcestring);
1817 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1818 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1819 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1820 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1821 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1822 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1824 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1825 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1826 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1827 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1828 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1829 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1831 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1833 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1834 if (r_hlsl_permutation != perm)
1836 r_hlsl_permutation = perm;
1837 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1839 if (!r_hlsl_permutation->compiled)
1840 R_HLSL_CompilePermutation(perm, mode, permutation);
1841 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1843 // remove features until we find a valid permutation
1845 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1847 // reduce i more quickly whenever it would not remove any bits
1848 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1849 if (!(permutation & j))
1852 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1853 if (!r_hlsl_permutation->compiled)
1854 R_HLSL_CompilePermutation(perm, mode, permutation);
1855 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1858 if (i >= SHADERPERMUTATION_COUNT)
1860 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1861 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1862 return; // no bit left to clear, entire mode is broken
1866 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1867 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1869 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1870 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1871 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1875 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1877 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1878 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1879 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1880 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1883 void R_GLSL_Restart_f(void)
1885 unsigned int i, limit;
1886 if (glslshaderstring)
1887 Mem_Free(glslshaderstring);
1888 glslshaderstring = NULL;
1889 if (hlslshaderstring)
1890 Mem_Free(hlslshaderstring);
1891 hlslshaderstring = NULL;
1892 switch(vid.renderpath)
1894 case RENDERPATH_D3D9:
1897 r_hlsl_permutation_t *p;
1898 r_hlsl_permutation = NULL;
1899 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1900 for (i = 0;i < limit;i++)
1902 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1904 if (p->vertexshader)
1905 IDirect3DVertexShader9_Release(p->vertexshader);
1907 IDirect3DPixelShader9_Release(p->pixelshader);
1908 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1911 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1915 case RENDERPATH_D3D10:
1916 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918 case RENDERPATH_D3D11:
1919 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1921 case RENDERPATH_GL20:
1922 case RENDERPATH_GLES2:
1924 r_glsl_permutation_t *p;
1925 r_glsl_permutation = NULL;
1926 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1927 for (i = 0;i < limit;i++)
1929 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1931 GL_Backend_FreeProgram(p->program);
1932 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1935 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1938 case RENDERPATH_GL11:
1939 case RENDERPATH_GL13:
1940 case RENDERPATH_GLES1:
1942 case RENDERPATH_SOFT:
1947 static void R_GLSL_DumpShader_f(void)
1949 int i, language, mode, dupe;
1951 shadermodeinfo_t *modeinfo;
1954 for (language = 0;language < 2;language++)
1956 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1957 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1959 // don't dump the same file multiple times (most or all shaders come from the same file)
1960 for (dupe = mode - 1;dupe >= 0;dupe--)
1961 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1965 text = R_GetShaderText(modeinfo[mode].filename, false, true);
1968 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1971 FS_Print(file, "/* The engine may define the following macros:\n");
1972 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1973 for (i = 0;i < SHADERMODE_COUNT;i++)
1974 FS_Print(file, modeinfo[i].pretext);
1975 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1976 FS_Print(file, shaderpermutationinfo[i].pretext);
1977 FS_Print(file, "*/\n");
1978 FS_Print(file, text);
1980 Con_Printf("%s written\n", modeinfo[mode].filename);
1983 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1989 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1991 unsigned int permutation = 0;
1992 if (r_trippy.integer && !notrippy)
1993 permutation |= SHADERPERMUTATION_TRIPPY;
1994 permutation |= SHADERPERMUTATION_VIEWTINT;
1996 permutation |= SHADERPERMUTATION_DIFFUSE;
1998 permutation |= SHADERPERMUTATION_SPECULAR;
1999 if (texturemode == GL_MODULATE)
2000 permutation |= SHADERPERMUTATION_COLORMAPPING;
2001 else if (texturemode == GL_ADD)
2002 permutation |= SHADERPERMUTATION_GLOW;
2003 else if (texturemode == GL_DECAL)
2004 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2005 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2006 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2007 if (suppresstexalpha)
2008 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2010 texturemode = GL_MODULATE;
2011 if (vid.allowalphatocoverage)
2012 GL_AlphaToCoverage(false);
2013 switch (vid.renderpath)
2015 case RENDERPATH_D3D9:
2017 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2018 R_Mesh_TexBind(GL20TU_FIRST , first );
2019 R_Mesh_TexBind(GL20TU_SECOND, second);
2020 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2021 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2024 case RENDERPATH_D3D10:
2025 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2027 case RENDERPATH_D3D11:
2028 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2030 case RENDERPATH_GL20:
2031 case RENDERPATH_GLES2:
2032 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2033 if (r_glsl_permutation->tex_Texture_First >= 0)
2034 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2035 if (r_glsl_permutation->tex_Texture_Second >= 0)
2036 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2037 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2038 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2040 case RENDERPATH_GL13:
2041 case RENDERPATH_GLES1:
2042 R_Mesh_TexBind(0, first );
2043 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2044 R_Mesh_TexMatrix(0, NULL);
2045 R_Mesh_TexBind(1, second);
2048 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2049 R_Mesh_TexMatrix(1, NULL);
2052 case RENDERPATH_GL11:
2053 R_Mesh_TexBind(0, first );
2054 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2055 R_Mesh_TexMatrix(0, NULL);
2057 case RENDERPATH_SOFT:
2058 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2059 R_Mesh_TexBind(GL20TU_FIRST , first );
2060 R_Mesh_TexBind(GL20TU_SECOND, second);
2065 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2067 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2070 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2072 unsigned int permutation = 0;
2073 if (r_trippy.integer && !notrippy)
2074 permutation |= SHADERPERMUTATION_TRIPPY;
2076 permutation |= SHADERPERMUTATION_DEPTHRGB;
2078 permutation |= SHADERPERMUTATION_SKELETAL;
2080 if (vid.allowalphatocoverage)
2081 GL_AlphaToCoverage(false);
2082 switch (vid.renderpath)
2084 case RENDERPATH_D3D9:
2086 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2089 case RENDERPATH_D3D10:
2090 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2092 case RENDERPATH_D3D11:
2093 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2095 case RENDERPATH_GL20:
2096 case RENDERPATH_GLES2:
2097 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2098 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2099 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2102 case RENDERPATH_GL13:
2103 case RENDERPATH_GLES1:
2104 R_Mesh_TexBind(0, 0);
2105 R_Mesh_TexBind(1, 0);
2107 case RENDERPATH_GL11:
2108 R_Mesh_TexBind(0, 0);
2110 case RENDERPATH_SOFT:
2111 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2116 extern qboolean r_shadow_usingdeferredprepass;
2117 extern rtexture_t *r_shadow_attenuationgradienttexture;
2118 extern rtexture_t *r_shadow_attenuation2dtexture;
2119 extern rtexture_t *r_shadow_attenuation3dtexture;
2120 extern qboolean r_shadow_usingshadowmap2d;
2121 extern qboolean r_shadow_usingshadowmaportho;
2122 extern float r_shadow_shadowmap_texturescale[2];
2123 extern float r_shadow_shadowmap_parameters[4];
2124 extern qboolean r_shadow_shadowmapvsdct;
2125 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2126 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2127 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2128 extern matrix4x4_t r_shadow_shadowmapmatrix;
2129 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2130 extern int r_shadow_prepass_width;
2131 extern int r_shadow_prepass_height;
2132 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2133 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2134 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2135 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2137 #define BLENDFUNC_ALLOWS_COLORMOD 1
2138 #define BLENDFUNC_ALLOWS_FOG 2
2139 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2140 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2141 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2142 static int R_BlendFuncFlags(int src, int dst)
2146 // a blendfunc allows colormod if:
2147 // a) it can never keep the destination pixel invariant, or
2148 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2149 // this is to prevent unintended side effects from colormod
2151 // a blendfunc allows fog if:
2152 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2153 // this is to prevent unintended side effects from fog
2155 // these checks are the output of fogeval.pl
2157 r |= BLENDFUNC_ALLOWS_COLORMOD;
2158 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2159 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2160 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2161 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2162 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2163 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2164 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2165 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2166 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2167 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2168 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2169 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2170 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2171 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2172 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2173 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2174 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2175 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2177 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2178 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2183 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2185 // select a permutation of the lighting shader appropriate to this
2186 // combination of texture, entity, light source, and fogging, only use the
2187 // minimum features necessary to avoid wasting rendering time in the
2188 // fragment shader on features that are not being used
2189 unsigned int permutation = 0;
2190 unsigned int mode = 0;
2192 static float dummy_colormod[3] = {1, 1, 1};
2193 float *colormod = rsurface.colormod;
2195 matrix4x4_t tempmatrix;
2196 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2197 if (r_trippy.integer && !notrippy)
2198 permutation |= SHADERPERMUTATION_TRIPPY;
2199 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2200 permutation |= SHADERPERMUTATION_ALPHAKILL;
2201 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2202 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2203 if (rsurfacepass == RSURFPASS_BACKGROUND)
2205 // distorted background
2206 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2208 mode = SHADERMODE_WATER;
2209 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2210 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2211 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2213 // this is the right thing to do for wateralpha
2214 GL_BlendFunc(GL_ONE, GL_ZERO);
2215 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2219 // this is the right thing to do for entity alpha
2220 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2221 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2224 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2226 mode = SHADERMODE_REFRACTION;
2227 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2228 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2229 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2230 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2234 mode = SHADERMODE_GENERIC;
2235 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2236 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2237 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2239 if (vid.allowalphatocoverage)
2240 GL_AlphaToCoverage(false);
2242 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2244 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2246 switch(rsurface.texture->offsetmapping)
2248 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2249 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2250 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2251 case OFFSETMAPPING_OFF: break;
2254 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2255 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2256 // normalmap (deferred prepass), may use alpha test on diffuse
2257 mode = SHADERMODE_DEFERREDGEOMETRY;
2258 GL_BlendFunc(GL_ONE, GL_ZERO);
2259 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2260 if (vid.allowalphatocoverage)
2261 GL_AlphaToCoverage(false);
2263 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2265 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2267 switch(rsurface.texture->offsetmapping)
2269 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2270 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2271 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2272 case OFFSETMAPPING_OFF: break;
2275 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2276 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2277 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2278 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2280 mode = SHADERMODE_LIGHTSOURCE;
2281 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2282 permutation |= SHADERPERMUTATION_CUBEFILTER;
2283 if (diffusescale > 0)
2284 permutation |= SHADERPERMUTATION_DIFFUSE;
2285 if (specularscale > 0)
2286 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2287 if (r_refdef.fogenabled)
2288 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2289 if (rsurface.texture->colormapping)
2290 permutation |= SHADERPERMUTATION_COLORMAPPING;
2291 if (r_shadow_usingshadowmap2d)
2293 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2294 if(r_shadow_shadowmapvsdct)
2295 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2297 if (r_shadow_shadowmap2ddepthbuffer)
2298 permutation |= SHADERPERMUTATION_DEPTHRGB;
2300 if (rsurface.texture->reflectmasktexture)
2301 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2302 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2303 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2304 if (vid.allowalphatocoverage)
2305 GL_AlphaToCoverage(false);
2307 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2309 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2311 switch(rsurface.texture->offsetmapping)
2313 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2314 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2316 case OFFSETMAPPING_OFF: break;
2319 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2320 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2321 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2322 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2323 // unshaded geometry (fullbright or ambient model lighting)
2324 mode = SHADERMODE_FLATCOLOR;
2325 ambientscale = diffusescale = specularscale = 0;
2326 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2327 permutation |= SHADERPERMUTATION_GLOW;
2328 if (r_refdef.fogenabled)
2329 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2330 if (rsurface.texture->colormapping)
2331 permutation |= SHADERPERMUTATION_COLORMAPPING;
2332 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2334 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2335 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2337 if (r_shadow_shadowmap2ddepthbuffer)
2338 permutation |= SHADERPERMUTATION_DEPTHRGB;
2340 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2341 permutation |= SHADERPERMUTATION_REFLECTION;
2342 if (rsurface.texture->reflectmasktexture)
2343 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2344 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2345 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2346 // when using alphatocoverage, we don't need alphakill
2347 if (vid.allowalphatocoverage)
2349 if (r_transparent_alphatocoverage.integer)
2351 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2352 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2355 GL_AlphaToCoverage(false);
2358 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2360 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2362 switch(rsurface.texture->offsetmapping)
2364 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2365 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2366 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2367 case OFFSETMAPPING_OFF: break;
2370 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2371 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2372 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2373 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2374 // directional model lighting
2375 mode = SHADERMODE_LIGHTDIRECTION;
2376 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2377 permutation |= SHADERPERMUTATION_GLOW;
2378 permutation |= SHADERPERMUTATION_DIFFUSE;
2379 if (specularscale > 0)
2380 permutation |= SHADERPERMUTATION_SPECULAR;
2381 if (r_refdef.fogenabled)
2382 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2383 if (rsurface.texture->colormapping)
2384 permutation |= SHADERPERMUTATION_COLORMAPPING;
2385 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2387 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2388 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2390 if (r_shadow_shadowmap2ddepthbuffer)
2391 permutation |= SHADERPERMUTATION_DEPTHRGB;
2393 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2394 permutation |= SHADERPERMUTATION_REFLECTION;
2395 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2396 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2397 if (rsurface.texture->reflectmasktexture)
2398 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2399 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2401 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2402 if (r_shadow_bouncegriddirectional)
2403 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2405 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2406 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2407 // when using alphatocoverage, we don't need alphakill
2408 if (vid.allowalphatocoverage)
2410 if (r_transparent_alphatocoverage.integer)
2412 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2413 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2416 GL_AlphaToCoverage(false);
2419 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2421 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2423 switch(rsurface.texture->offsetmapping)
2425 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2426 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2427 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2428 case OFFSETMAPPING_OFF: break;
2431 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2432 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2434 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2435 // ambient model lighting
2436 mode = SHADERMODE_LIGHTDIRECTION;
2437 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2438 permutation |= SHADERPERMUTATION_GLOW;
2439 if (r_refdef.fogenabled)
2440 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2441 if (rsurface.texture->colormapping)
2442 permutation |= SHADERPERMUTATION_COLORMAPPING;
2443 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2445 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2446 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2448 if (r_shadow_shadowmap2ddepthbuffer)
2449 permutation |= SHADERPERMUTATION_DEPTHRGB;
2451 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2452 permutation |= SHADERPERMUTATION_REFLECTION;
2453 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2454 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2455 if (rsurface.texture->reflectmasktexture)
2456 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2457 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2459 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2460 if (r_shadow_bouncegriddirectional)
2461 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2463 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2464 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2465 // when using alphatocoverage, we don't need alphakill
2466 if (vid.allowalphatocoverage)
2468 if (r_transparent_alphatocoverage.integer)
2470 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2471 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2474 GL_AlphaToCoverage(false);
2479 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2481 switch(rsurface.texture->offsetmapping)
2483 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2484 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2485 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2486 case OFFSETMAPPING_OFF: break;
2489 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2490 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2491 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2492 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2494 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2495 permutation |= SHADERPERMUTATION_GLOW;
2496 if (r_refdef.fogenabled)
2497 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2498 if (rsurface.texture->colormapping)
2499 permutation |= SHADERPERMUTATION_COLORMAPPING;
2500 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2502 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2503 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2505 if (r_shadow_shadowmap2ddepthbuffer)
2506 permutation |= SHADERPERMUTATION_DEPTHRGB;
2508 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2509 permutation |= SHADERPERMUTATION_REFLECTION;
2510 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2511 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2512 if (rsurface.texture->reflectmasktexture)
2513 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2514 if (FAKELIGHT_ENABLED)
2516 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2517 mode = SHADERMODE_FAKELIGHT;
2518 permutation |= SHADERPERMUTATION_DIFFUSE;
2519 if (specularscale > 0)
2520 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2522 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2524 // deluxemapping (light direction texture)
2525 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2526 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2528 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2529 permutation |= SHADERPERMUTATION_DIFFUSE;
2530 if (specularscale > 0)
2531 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2533 else if (r_glsl_deluxemapping.integer >= 2)
2535 // fake deluxemapping (uniform light direction in tangentspace)
2536 if (rsurface.uselightmaptexture)
2537 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2539 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2540 permutation |= SHADERPERMUTATION_DIFFUSE;
2541 if (specularscale > 0)
2542 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2544 else if (rsurface.uselightmaptexture)
2546 // ordinary lightmapping (q1bsp, q3bsp)
2547 mode = SHADERMODE_LIGHTMAP;
2551 // ordinary vertex coloring (q3bsp)
2552 mode = SHADERMODE_VERTEXCOLOR;
2554 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2556 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2557 if (r_shadow_bouncegriddirectional)
2558 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2560 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2561 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2562 // when using alphatocoverage, we don't need alphakill
2563 if (vid.allowalphatocoverage)
2565 if (r_transparent_alphatocoverage.integer)
2567 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2568 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2571 GL_AlphaToCoverage(false);
2574 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2575 colormod = dummy_colormod;
2576 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2577 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2578 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2579 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2580 switch(vid.renderpath)
2582 case RENDERPATH_D3D9:
2584 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2585 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2586 R_SetupShader_SetPermutationHLSL(mode, permutation);
2587 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2588 if (mode == SHADERMODE_LIGHTSOURCE)
2590 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2591 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2595 if (mode == SHADERMODE_LIGHTDIRECTION)
2597 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2600 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2601 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2602 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2603 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2604 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2606 if (mode == SHADERMODE_LIGHTSOURCE)
2608 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2609 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2610 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2611 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2612 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2614 // additive passes are only darkened by fog, not tinted
2615 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2616 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2620 if (mode == SHADERMODE_FLATCOLOR)
2622 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2624 else if (mode == SHADERMODE_LIGHTDIRECTION)
2626 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2627 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2628 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2629 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2630 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2631 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2632 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2636 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2637 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2638 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2639 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2640 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2642 // additive passes are only darkened by fog, not tinted
2643 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2644 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2646 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2647 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2648 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2649 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2650 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2651 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2652 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2653 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2654 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2655 if (mode == SHADERMODE_WATER)
2656 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2658 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2659 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2660 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2661 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2662 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2663 if (rsurface.texture->pantstexture)
2664 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2666 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2667 if (rsurface.texture->shirttexture)
2668 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2670 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2671 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2672 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2673 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2674 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2675 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2676 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2677 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2678 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2679 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2681 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2682 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2683 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2684 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2686 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2687 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2688 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2689 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2690 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2691 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2692 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2693 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2694 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2695 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2696 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2697 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2698 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2699 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2700 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2701 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2702 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2703 if (rsurfacepass == RSURFPASS_BACKGROUND)
2705 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2706 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2707 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2711 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2713 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2714 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2715 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2716 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2718 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2719 if (rsurface.rtlight)
2721 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2722 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2727 case RENDERPATH_D3D10:
2728 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2730 case RENDERPATH_D3D11:
2731 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2733 case RENDERPATH_GL20:
2734 case RENDERPATH_GLES2:
2735 if (!vid.useinterleavedarrays)
2737 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2738 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2739 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2740 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2741 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2742 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2743 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2744 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2745 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2746 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2747 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2751 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2752 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2754 // this has to be after RSurf_PrepareVerticesForBatch
2755 if (rsurface.batchskeletaltransform3x4buffer)
2756 permutation |= SHADERPERMUTATION_SKELETAL;
2757 R_SetupShader_SetPermutationGLSL(mode, permutation);
2758 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2759 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2761 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2762 if (mode == SHADERMODE_LIGHTSOURCE)
2764 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2765 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2766 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2767 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2768 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2769 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2771 // additive passes are only darkened by fog, not tinted
2772 if (r_glsl_permutation->loc_FogColor >= 0)
2773 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2774 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2778 if (mode == SHADERMODE_FLATCOLOR)
2780 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2782 else if (mode == SHADERMODE_LIGHTDIRECTION)
2784 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2785 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2786 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2787 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2788 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2789 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2790 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2794 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2795 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2796 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2797 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2798 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2800 // additive passes are only darkened by fog, not tinted
2801 if (r_glsl_permutation->loc_FogColor >= 0)
2803 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2804 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2806 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2808 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2809 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2810 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2811 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2812 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2813 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2814 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2815 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2816 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2818 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2819 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2820 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2821 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2822 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2824 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2825 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2826 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2827 if (r_glsl_permutation->loc_Color_Pants >= 0)
2829 if (rsurface.texture->pantstexture)
2830 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2832 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2834 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2836 if (rsurface.texture->shirttexture)
2837 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2839 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2841 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2842 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2843 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2844 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2845 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2846 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2847 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2848 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2849 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2851 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2852 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2853 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2854 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2855 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2856 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2858 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2859 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2860 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2861 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2862 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2863 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2864 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2865 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2866 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2867 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2868 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2869 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2870 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2871 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2872 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2873 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2874 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2875 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2876 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2877 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2878 if (rsurfacepass == RSURFPASS_BACKGROUND)
2880 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2881 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2882 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2886 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2888 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2889 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2890 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2891 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2893 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2894 if (rsurface.rtlight)
2896 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2897 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2900 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2903 case RENDERPATH_GL11:
2904 case RENDERPATH_GL13:
2905 case RENDERPATH_GLES1:
2907 case RENDERPATH_SOFT:
2908 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2909 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2910 R_SetupShader_SetPermutationSoft(mode, permutation);
2911 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2912 if (mode == SHADERMODE_LIGHTSOURCE)
2914 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2915 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2916 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2917 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2918 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2919 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2921 // additive passes are only darkened by fog, not tinted
2922 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2923 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2927 if (mode == SHADERMODE_FLATCOLOR)
2929 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2931 else if (mode == SHADERMODE_LIGHTDIRECTION)
2933 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2934 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2935 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2936 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2937 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2938 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2939 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2943 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2944 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2945 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2946 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2947 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2949 // additive passes are only darkened by fog, not tinted
2950 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2951 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2953 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2954 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2955 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2956 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2957 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2958 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2959 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2960 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2961 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2962 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2964 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2965 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2966 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2967 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2968 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2970 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2971 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2972 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2973 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2975 if (rsurface.texture->pantstexture)
2976 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2978 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2980 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2982 if (rsurface.texture->shirttexture)
2983 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2985 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2987 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2988 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2989 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2990 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2991 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2992 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2993 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2994 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2995 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2997 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2998 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2999 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3000 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3002 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3003 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3004 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3005 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3006 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3007 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3008 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3009 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3010 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3011 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3012 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3013 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3014 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3015 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3016 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3017 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3018 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3019 if (rsurfacepass == RSURFPASS_BACKGROUND)
3021 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3022 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3023 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3027 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3029 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3030 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3031 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3032 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3034 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3035 if (rsurface.rtlight)
3037 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3038 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3045 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3047 // select a permutation of the lighting shader appropriate to this
3048 // combination of texture, entity, light source, and fogging, only use the
3049 // minimum features necessary to avoid wasting rendering time in the
3050 // fragment shader on features that are not being used
3051 unsigned int permutation = 0;
3052 unsigned int mode = 0;
3053 const float *lightcolorbase = rtlight->currentcolor;
3054 float ambientscale = rtlight->ambientscale;
3055 float diffusescale = rtlight->diffusescale;
3056 float specularscale = rtlight->specularscale;
3057 // this is the location of the light in view space
3058 vec3_t viewlightorigin;
3059 // this transforms from view space (camera) to light space (cubemap)
3060 matrix4x4_t viewtolight;
3061 matrix4x4_t lighttoview;
3062 float viewtolight16f[16];
3064 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3065 if (rtlight->currentcubemap != r_texture_whitecube)
3066 permutation |= SHADERPERMUTATION_CUBEFILTER;
3067 if (diffusescale > 0)
3068 permutation |= SHADERPERMUTATION_DIFFUSE;
3069 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3070 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3071 if (r_shadow_usingshadowmap2d)
3073 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3074 if (r_shadow_shadowmapvsdct)
3075 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3077 if (r_shadow_shadowmap2ddepthbuffer)
3078 permutation |= SHADERPERMUTATION_DEPTHRGB;
3080 if (vid.allowalphatocoverage)
3081 GL_AlphaToCoverage(false);
3082 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3083 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3084 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3085 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3086 switch(vid.renderpath)
3088 case RENDERPATH_D3D9:
3090 R_SetupShader_SetPermutationHLSL(mode, permutation);
3091 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3092 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3093 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3094 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3095 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3096 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3097 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3098 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3099 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3100 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3102 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3103 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3104 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3105 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3106 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3109 case RENDERPATH_D3D10:
3110 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3112 case RENDERPATH_D3D11:
3113 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3115 case RENDERPATH_GL20:
3116 case RENDERPATH_GLES2:
3117 R_SetupShader_SetPermutationGLSL(mode, permutation);
3118 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3119 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3120 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3121 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3122 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3123 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3124 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3125 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3126 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3127 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3129 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3130 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3131 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3132 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3133 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3135 case RENDERPATH_GL11:
3136 case RENDERPATH_GL13:
3137 case RENDERPATH_GLES1:
3139 case RENDERPATH_SOFT:
3140 R_SetupShader_SetPermutationGLSL(mode, permutation);
3141 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3142 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3143 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3144 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3145 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3146 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3147 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3148 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3149 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3150 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3152 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3153 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3154 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3155 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3156 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3161 #define SKINFRAME_HASH 1024
3165 int loadsequence; // incremented each level change
3166 memexpandablearray_t array;
3167 skinframe_t *hash[SKINFRAME_HASH];
3170 r_skinframe_t r_skinframe;
3172 void R_SkinFrame_PrepareForPurge(void)
3174 r_skinframe.loadsequence++;
3175 // wrap it without hitting zero
3176 if (r_skinframe.loadsequence >= 200)
3177 r_skinframe.loadsequence = 1;
3180 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3184 // mark the skinframe as used for the purging code
3185 skinframe->loadsequence = r_skinframe.loadsequence;
3188 void R_SkinFrame_Purge(void)
3192 for (i = 0;i < SKINFRAME_HASH;i++)
3194 for (s = r_skinframe.hash[i];s;s = s->next)
3196 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3198 if (s->merged == s->base)
3200 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3201 R_PurgeTexture(s->stain );s->stain = NULL;
3202 R_PurgeTexture(s->merged);s->merged = NULL;
3203 R_PurgeTexture(s->base );s->base = NULL;
3204 R_PurgeTexture(s->pants );s->pants = NULL;
3205 R_PurgeTexture(s->shirt );s->shirt = NULL;
3206 R_PurgeTexture(s->nmap );s->nmap = NULL;
3207 R_PurgeTexture(s->gloss );s->gloss = NULL;
3208 R_PurgeTexture(s->glow );s->glow = NULL;
3209 R_PurgeTexture(s->fog );s->fog = NULL;
3210 R_PurgeTexture(s->reflect);s->reflect = NULL;
3211 s->loadsequence = 0;
3217 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3219 char basename[MAX_QPATH];
3221 Image_StripImageExtension(name, basename, sizeof(basename));
3223 if( last == NULL ) {
3225 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3226 item = r_skinframe.hash[hashindex];
3231 // linearly search through the hash bucket
3232 for( ; item ; item = item->next ) {
3233 if( !strcmp( item->basename, basename ) ) {
3240 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3244 char basename[MAX_QPATH];
3246 Image_StripImageExtension(name, basename, sizeof(basename));
3248 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3249 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3250 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3254 rtexture_t *dyntexture;
3255 // check whether its a dynamic texture
3256 dyntexture = CL_GetDynTexture( basename );
3257 if (!add && !dyntexture)
3259 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3260 memset(item, 0, sizeof(*item));
3261 strlcpy(item->basename, basename, sizeof(item->basename));
3262 item->base = dyntexture; // either NULL or dyntexture handle
3263 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3264 item->comparewidth = comparewidth;
3265 item->compareheight = compareheight;
3266 item->comparecrc = comparecrc;
3267 item->next = r_skinframe.hash[hashindex];
3268 r_skinframe.hash[hashindex] = item;
3270 else if (textureflags & TEXF_FORCE_RELOAD)
3272 rtexture_t *dyntexture;
3273 // check whether its a dynamic texture
3274 dyntexture = CL_GetDynTexture( basename );
3275 if (!add && !dyntexture)
3277 if (item->merged == item->base)
3278 item->merged = NULL;
3279 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3280 R_PurgeTexture(item->stain );item->stain = NULL;
3281 R_PurgeTexture(item->merged);item->merged = NULL;
3282 R_PurgeTexture(item->base );item->base = NULL;
3283 R_PurgeTexture(item->pants );item->pants = NULL;
3284 R_PurgeTexture(item->shirt );item->shirt = NULL;
3285 R_PurgeTexture(item->nmap );item->nmap = NULL;
3286 R_PurgeTexture(item->gloss );item->gloss = NULL;
3287 R_PurgeTexture(item->glow );item->glow = NULL;
3288 R_PurgeTexture(item->fog );item->fog = NULL;
3289 R_PurgeTexture(item->reflect);item->reflect = NULL;
3290 item->loadsequence = 0;
3292 else if( item->base == NULL )
3294 rtexture_t *dyntexture;
3295 // check whether its a dynamic texture
3296 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3297 dyntexture = CL_GetDynTexture( basename );
3298 item->base = dyntexture; // either NULL or dyntexture handle
3301 R_SkinFrame_MarkUsed(item);
3305 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3307 unsigned long long avgcolor[5], wsum; \
3315 for(pix = 0; pix < cnt; ++pix) \
3318 for(comp = 0; comp < 3; ++comp) \
3320 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3323 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3325 for(comp = 0; comp < 3; ++comp) \
3326 avgcolor[comp] += getpixel * w; \
3329 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3330 avgcolor[4] += getpixel; \
3332 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3334 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3335 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3336 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3337 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3340 extern cvar_t gl_picmip;
3341 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3344 unsigned char *pixels;
3345 unsigned char *bumppixels;
3346 unsigned char *basepixels = NULL;
3347 int basepixels_width = 0;
3348 int basepixels_height = 0;
3349 skinframe_t *skinframe;
3350 rtexture_t *ddsbase = NULL;
3351 qboolean ddshasalpha = false;
3352 float ddsavgcolor[4];
3353 char basename[MAX_QPATH];
3354 int miplevel = R_PicmipForFlags(textureflags);
3355 int savemiplevel = miplevel;
3359 if (cls.state == ca_dedicated)
3362 // return an existing skinframe if already loaded
3363 // if loading of the first image fails, don't make a new skinframe as it
3364 // would cause all future lookups of this to be missing
3365 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3366 if (skinframe && skinframe->base)
3369 Image_StripImageExtension(name, basename, sizeof(basename));
3371 // check for DDS texture file first
3372 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3374 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3375 if (basepixels == NULL)
3379 // FIXME handle miplevel
3381 if (developer_loading.integer)
3382 Con_Printf("loading skin \"%s\"\n", name);
3384 // we've got some pixels to store, so really allocate this new texture now
3386 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3387 textureflags &= ~TEXF_FORCE_RELOAD;
3388 skinframe->stain = NULL;
3389 skinframe->merged = NULL;
3390 skinframe->base = NULL;
3391 skinframe->pants = NULL;
3392 skinframe->shirt = NULL;
3393 skinframe->nmap = NULL;
3394 skinframe->gloss = NULL;
3395 skinframe->glow = NULL;
3396 skinframe->fog = NULL;
3397 skinframe->reflect = NULL;
3398 skinframe->hasalpha = false;
3402 skinframe->base = ddsbase;
3403 skinframe->hasalpha = ddshasalpha;
3404 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3405 if (r_loadfog && skinframe->hasalpha)
3406 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3407 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3411 basepixels_width = image_width;
3412 basepixels_height = image_height;
3413 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3414 if (textureflags & TEXF_ALPHA)
3416 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3418 if (basepixels[j] < 255)
3420 skinframe->hasalpha = true;
3424 if (r_loadfog && skinframe->hasalpha)
3426 // has transparent pixels
3427 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3428 for (j = 0;j < image_width * image_height * 4;j += 4)
3433 pixels[j+3] = basepixels[j+3];
3435 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3439 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3441 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3442 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3443 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3444 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3445 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3451 mymiplevel = savemiplevel;
3452 if (r_loadnormalmap)
3453 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3454 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3456 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3457 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3458 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3459 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3462 // _norm is the name used by tenebrae and has been adopted as standard
3463 if (r_loadnormalmap && skinframe->nmap == NULL)
3465 mymiplevel = savemiplevel;
3466 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3468 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3472 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3474 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3475 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3476 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3478 Mem_Free(bumppixels);
3480 else if (r_shadow_bumpscale_basetexture.value > 0)
3482 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3483 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3484 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3488 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3489 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3493 // _luma is supported only for tenebrae compatibility
3494 // _glow is the preferred name
3495 mymiplevel = savemiplevel;
3496 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3498 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3500 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3501 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3503 Mem_Free(pixels);pixels = NULL;
3506 mymiplevel = savemiplevel;
3507 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3509 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3511 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3512 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3518 mymiplevel = savemiplevel;
3519 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3521 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3523 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3524 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3530 mymiplevel = savemiplevel;
3531 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3533 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3535 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3536 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3542 mymiplevel = savemiplevel;
3543 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3545 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3547 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3548 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3555 Mem_Free(basepixels);
3560 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3561 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3564 unsigned char *temp1, *temp2;
3565 skinframe_t *skinframe;
3568 if (cls.state == ca_dedicated)
3571 // if already loaded just return it, otherwise make a new skinframe
3572 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3573 if (skinframe->base)
3575 textureflags &= ~TEXF_FORCE_RELOAD;
3577 skinframe->stain = NULL;
3578 skinframe->merged = NULL;
3579 skinframe->base = NULL;
3580 skinframe->pants = NULL;
3581 skinframe->shirt = NULL;
3582 skinframe->nmap = NULL;
3583 skinframe->gloss = NULL;
3584 skinframe->glow = NULL;
3585 skinframe->fog = NULL;
3586 skinframe->reflect = NULL;
3587 skinframe->hasalpha = false;
3589 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3593 if (developer_loading.integer)
3594 Con_Printf("loading 32bit skin \"%s\"\n", name);
3596 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3598 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3599 temp2 = temp1 + width * height * 4;
3600 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3601 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3604 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3605 if (textureflags & TEXF_ALPHA)
3607 for (i = 3;i < width * height * 4;i += 4)
3609 if (skindata[i] < 255)
3611 skinframe->hasalpha = true;
3615 if (r_loadfog && skinframe->hasalpha)
3617 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3618 memcpy(fogpixels, skindata, width * height * 4);
3619 for (i = 0;i < width * height * 4;i += 4)
3620 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3621 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3622 Mem_Free(fogpixels);
3626 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3627 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3632 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3636 skinframe_t *skinframe;
3638 if (cls.state == ca_dedicated)
3641 // if already loaded just return it, otherwise make a new skinframe
3642 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3643 if (skinframe->base)
3645 //textureflags &= ~TEXF_FORCE_RELOAD;
3647 skinframe->stain = NULL;
3648 skinframe->merged = NULL;
3649 skinframe->base = NULL;
3650 skinframe->pants = NULL;
3651 skinframe->shirt = NULL;
3652 skinframe->nmap = NULL;
3653 skinframe->gloss = NULL;
3654 skinframe->glow = NULL;
3655 skinframe->fog = NULL;
3656 skinframe->reflect = NULL;
3657 skinframe->hasalpha = false;
3659 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3663 if (developer_loading.integer)
3664 Con_Printf("loading quake skin \"%s\"\n", name);
3666 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3667 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3668 memcpy(skinframe->qpixels, skindata, width*height);
3669 skinframe->qwidth = width;
3670 skinframe->qheight = height;
3673 for (i = 0;i < width * height;i++)
3674 featuresmask |= palette_featureflags[skindata[i]];
3676 skinframe->hasalpha = false;
3677 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3678 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3679 skinframe->qgeneratemerged = true;
3680 skinframe->qgeneratebase = skinframe->qhascolormapping;
3681 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3683 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3684 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3689 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3693 unsigned char *skindata;
3696 if (!skinframe->qpixels)
3699 if (!skinframe->qhascolormapping)
3700 colormapped = false;
3704 if (!skinframe->qgeneratebase)
3709 if (!skinframe->qgeneratemerged)
3713 width = skinframe->qwidth;
3714 height = skinframe->qheight;
3715 skindata = skinframe->qpixels;
3717 if (skinframe->qgeneratenmap)
3719 unsigned char *temp1, *temp2;
3720 skinframe->qgeneratenmap = false;
3721 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3722 temp2 = temp1 + width * height * 4;
3723 // use either a custom palette or the quake palette
3724 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3725 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3726 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3730 if (skinframe->qgenerateglow)
3732 skinframe->qgenerateglow = false;
3733 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3738 skinframe->qgeneratebase = false;
3739 skinframe->base = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3740 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3741 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3745 skinframe->qgeneratemerged = false;
3746 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3749 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3751 Mem_Free(skinframe->qpixels);
3752 skinframe->qpixels = NULL;
3756 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3759 skinframe_t *skinframe;
3762 if (cls.state == ca_dedicated)
3765 // if already loaded just return it, otherwise make a new skinframe
3766 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3767 if (skinframe->base)
3769 textureflags &= ~TEXF_FORCE_RELOAD;
3771 skinframe->stain = NULL;
3772 skinframe->merged = NULL;
3773 skinframe->base = NULL;
3774 skinframe->pants = NULL;
3775 skinframe->shirt = NULL;
3776 skinframe->nmap = NULL;
3777 skinframe->gloss = NULL;
3778 skinframe->glow = NULL;
3779 skinframe->fog = NULL;
3780 skinframe->reflect = NULL;
3781 skinframe->hasalpha = false;
3783 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3787 if (developer_loading.integer)
3788 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3790 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3791 if (textureflags & TEXF_ALPHA)
3793 for (i = 0;i < width * height;i++)
3795 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3797 skinframe->hasalpha = true;
3801 if (r_loadfog && skinframe->hasalpha)
3802 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3805 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3806 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3811 skinframe_t *R_SkinFrame_LoadMissing(void)
3813 skinframe_t *skinframe;
3815 if (cls.state == ca_dedicated)
3818 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3819 skinframe->stain = NULL;
3820 skinframe->merged = NULL;
3821 skinframe->base = NULL;
3822 skinframe->pants = NULL;
3823 skinframe->shirt = NULL;
3824 skinframe->nmap = NULL;
3825 skinframe->gloss = NULL;
3826 skinframe->glow = NULL;
3827 skinframe->fog = NULL;
3828 skinframe->reflect = NULL;
3829 skinframe->hasalpha = false;
3831 skinframe->avgcolor[0] = rand() / RAND_MAX;
3832 skinframe->avgcolor[1] = rand() / RAND_MAX;
3833 skinframe->avgcolor[2] = rand() / RAND_MAX;
3834 skinframe->avgcolor[3] = 1;
3839 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3840 typedef struct suffixinfo_s
3843 qboolean flipx, flipy, flipdiagonal;
3846 static suffixinfo_t suffix[3][6] =
3849 {"px", false, false, false},
3850 {"nx", false, false, false},
3851 {"py", false, false, false},
3852 {"ny", false, false, false},
3853 {"pz", false, false, false},
3854 {"nz", false, false, false}
3857 {"posx", false, false, false},
3858 {"negx", false, false, false},
3859 {"posy", false, false, false},
3860 {"negy", false, false, false},
3861 {"posz", false, false, false},
3862 {"negz", false, false, false}
3865 {"rt", true, false, true},
3866 {"lf", false, true, true},
3867 {"ft", true, true, false},
3868 {"bk", false, false, false},
3869 {"up", true, false, true},
3870 {"dn", true, false, true}
3874 static int componentorder[4] = {0, 1, 2, 3};
3876 static rtexture_t *R_LoadCubemap(const char *basename)
3878 int i, j, cubemapsize;
3879 unsigned char *cubemappixels, *image_buffer;
3880 rtexture_t *cubemaptexture;
3882 // must start 0 so the first loadimagepixels has no requested width/height
3884 cubemappixels = NULL;
3885 cubemaptexture = NULL;
3886 // keep trying different suffix groups (posx, px, rt) until one loads
3887 for (j = 0;j < 3 && !cubemappixels;j++)
3889 // load the 6 images in the suffix group
3890 for (i = 0;i < 6;i++)
3892 // generate an image name based on the base and and suffix
3893 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3895 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3897 // an image loaded, make sure width and height are equal
3898 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3900 // if this is the first image to load successfully, allocate the cubemap memory
3901 if (!cubemappixels && image_width >= 1)
3903 cubemapsize = image_width;
3904 // note this clears to black, so unavailable sides are black
3905 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3907 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3909 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3912 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3914 Mem_Free(image_buffer);
3918 // if a cubemap loaded, upload it
3921 if (developer_loading.integer)
3922 Con_Printf("loading cubemap \"%s\"\n", basename);
3924 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3925 Mem_Free(cubemappixels);
3929 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3930 if (developer_loading.integer)
3932 Con_Printf("(tried tried images ");
3933 for (j = 0;j < 3;j++)
3934 for (i = 0;i < 6;i++)
3935 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3936 Con_Print(" and was unable to find any of them).\n");
3939 return cubemaptexture;
3942 rtexture_t *R_GetCubemap(const char *basename)
3945 for (i = 0;i < r_texture_numcubemaps;i++)
3946 if (r_texture_cubemaps[i] != NULL)
3947 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3948 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3949 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3950 return r_texture_whitecube;
3951 r_texture_numcubemaps++;
3952 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3953 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3954 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3955 return r_texture_cubemaps[i]->texture;
3958 static void R_Main_FreeViewCache(void)
3960 if (r_refdef.viewcache.entityvisible)
3961 Mem_Free(r_refdef.viewcache.entityvisible);
3962 if (r_refdef.viewcache.world_pvsbits)
3963 Mem_Free(r_refdef.viewcache.world_pvsbits);
3964 if (r_refdef.viewcache.world_leafvisible)
3965 Mem_Free(r_refdef.viewcache.world_leafvisible);
3966 if (r_refdef.viewcache.world_surfacevisible)
3967 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3968 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3971 static void R_Main_ResizeViewCache(void)
3973 int numentities = r_refdef.scene.numentities;
3974 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3975 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3976 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3977 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3978 if (r_refdef.viewcache.maxentities < numentities)
3980 r_refdef.viewcache.maxentities = numentities;
3981 if (r_refdef.viewcache.entityvisible)
3982 Mem_Free(r_refdef.viewcache.entityvisible);
3983 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3985 if (r_refdef.viewcache.world_numclusters != numclusters)
3987 r_refdef.viewcache.world_numclusters = numclusters;
3988 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3989 if (r_refdef.viewcache.world_pvsbits)
3990 Mem_Free(r_refdef.viewcache.world_pvsbits);
3991 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3993 if (r_refdef.viewcache.world_numleafs != numleafs)
3995 r_refdef.viewcache.world_numleafs = numleafs;
3996 if (r_refdef.viewcache.world_leafvisible)
3997 Mem_Free(r_refdef.viewcache.world_leafvisible);
3998 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4000 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4002 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4003 if (r_refdef.viewcache.world_surfacevisible)
4004 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4005 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4009 extern rtexture_t *loadingscreentexture;
4010 static void gl_main_start(void)
4012 loadingscreentexture = NULL;
4013 r_texture_blanknormalmap = NULL;
4014 r_texture_white = NULL;
4015 r_texture_grey128 = NULL;
4016 r_texture_black = NULL;
4017 r_texture_whitecube = NULL;
4018 r_texture_normalizationcube = NULL;
4019 r_texture_fogattenuation = NULL;
4020 r_texture_fogheighttexture = NULL;
4021 r_texture_gammaramps = NULL;
4022 r_texture_numcubemaps = 0;
4023 r_uniformbufferalignment = 32;
4025 r_loaddds = r_texture_dds_load.integer != 0;
4026 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4028 switch(vid.renderpath)
4030 case RENDERPATH_GL20:
4031 case RENDERPATH_D3D9:
4032 case RENDERPATH_D3D10:
4033 case RENDERPATH_D3D11:
4034 case RENDERPATH_SOFT:
4035 case RENDERPATH_GLES2:
4036 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4037 Cvar_SetValueQuick(&gl_combine, 1);
4038 Cvar_SetValueQuick(&r_glsl, 1);
4039 r_loadnormalmap = true;
4042 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4043 if (vid.support.arb_uniform_buffer_object)
4044 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4047 case RENDERPATH_GL13:
4048 case RENDERPATH_GLES1:
4049 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4050 Cvar_SetValueQuick(&gl_combine, 1);
4051 Cvar_SetValueQuick(&r_glsl, 0);
4052 r_loadnormalmap = false;
4053 r_loadgloss = false;
4056 case RENDERPATH_GL11:
4057 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4058 Cvar_SetValueQuick(&gl_combine, 0);
4059 Cvar_SetValueQuick(&r_glsl, 0);
4060 r_loadnormalmap = false;
4061 r_loadgloss = false;
4067 R_FrameData_Reset();
4068 R_BufferData_Reset();
4072 memset(r_queries, 0, sizeof(r_queries));
4074 r_qwskincache = NULL;
4075 r_qwskincache_size = 0;
4077 // due to caching of texture_t references, the collision cache must be reset
4078 Collision_Cache_Reset(true);
4080 // set up r_skinframe loading system for textures
4081 memset(&r_skinframe, 0, sizeof(r_skinframe));
4082 r_skinframe.loadsequence = 1;
4083 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4085 r_main_texturepool = R_AllocTexturePool();
4086 R_BuildBlankTextures();
4088 if (vid.support.arb_texture_cube_map)
4091 R_BuildNormalizationCube();
4093 r_texture_fogattenuation = NULL;
4094 r_texture_fogheighttexture = NULL;
4095 r_texture_gammaramps = NULL;
4096 //r_texture_fogintensity = NULL;
4097 memset(&r_fb, 0, sizeof(r_fb));
4098 r_glsl_permutation = NULL;
4099 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4100 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4101 glslshaderstring = NULL;
4103 r_hlsl_permutation = NULL;
4104 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4105 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4107 hlslshaderstring = NULL;
4108 memset(&r_svbsp, 0, sizeof (r_svbsp));
4110 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4111 r_texture_numcubemaps = 0;
4113 r_refdef.fogmasktable_density = 0;
4116 // For Steelstorm Android
4117 // FIXME CACHE the program and reload
4118 // FIXME see possible combinations for SS:BR android
4119 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4120 R_SetupShader_SetPermutationGLSL(0, 12);
4121 R_SetupShader_SetPermutationGLSL(0, 13);
4122 R_SetupShader_SetPermutationGLSL(0, 8388621);
4123 R_SetupShader_SetPermutationGLSL(3, 0);
4124 R_SetupShader_SetPermutationGLSL(3, 2048);
4125 R_SetupShader_SetPermutationGLSL(5, 0);
4126 R_SetupShader_SetPermutationGLSL(5, 2);
4127 R_SetupShader_SetPermutationGLSL(5, 2048);
4128 R_SetupShader_SetPermutationGLSL(5, 8388608);
4129 R_SetupShader_SetPermutationGLSL(11, 1);
4130 R_SetupShader_SetPermutationGLSL(11, 2049);
4131 R_SetupShader_SetPermutationGLSL(11, 8193);
4132 R_SetupShader_SetPermutationGLSL(11, 10241);
4133 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4137 static void gl_main_shutdown(void)
4140 R_FrameData_Reset();
4141 R_BufferData_Reset();
4143 R_Main_FreeViewCache();
4145 switch(vid.renderpath)
4147 case RENDERPATH_GL11:
4148 case RENDERPATH_GL13:
4149 case RENDERPATH_GL20:
4150 case RENDERPATH_GLES1:
4151 case RENDERPATH_GLES2:
4152 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4154 qglDeleteQueriesARB(r_maxqueries, r_queries);
4157 case RENDERPATH_D3D9:
4158 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4160 case RENDERPATH_D3D10:
4161 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4163 case RENDERPATH_D3D11:
4164 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4166 case RENDERPATH_SOFT:
4172 memset(r_queries, 0, sizeof(r_queries));
4174 r_qwskincache = NULL;
4175 r_qwskincache_size = 0;
4177 // clear out the r_skinframe state
4178 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4179 memset(&r_skinframe, 0, sizeof(r_skinframe));
4182 Mem_Free(r_svbsp.nodes);
4183 memset(&r_svbsp, 0, sizeof (r_svbsp));
4184 R_FreeTexturePool(&r_main_texturepool);
4185 loadingscreentexture = NULL;
4186 r_texture_blanknormalmap = NULL;
4187 r_texture_white = NULL;
4188 r_texture_grey128 = NULL;
4189 r_texture_black = NULL;
4190 r_texture_whitecube = NULL;
4191 r_texture_normalizationcube = NULL;
4192 r_texture_fogattenuation = NULL;
4193 r_texture_fogheighttexture = NULL;
4194 r_texture_gammaramps = NULL;
4195 r_texture_numcubemaps = 0;
4196 //r_texture_fogintensity = NULL;
4197 memset(&r_fb, 0, sizeof(r_fb));
4200 r_glsl_permutation = NULL;
4201 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4202 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4203 glslshaderstring = NULL;
4205 r_hlsl_permutation = NULL;
4206 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4207 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4209 hlslshaderstring = NULL;
4212 static void gl_main_newmap(void)
4214 // FIXME: move this code to client
4215 char *entities, entname[MAX_QPATH];
4217 Mem_Free(r_qwskincache);
4218 r_qwskincache = NULL;
4219 r_qwskincache_size = 0;
4222 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4223 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4225 CL_ParseEntityLump(entities);
4229 if (cl.worldmodel->brush.entities)
4230 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4232 R_Main_FreeViewCache();
4234 R_FrameData_Reset();
4235 R_BufferData_Reset();
4238 void GL_Main_Init(void)
4241 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4243 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4244 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4245 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4246 if (gamemode == GAME_NEHAHRA)
4248 Cvar_RegisterVariable (&gl_fogenable);
4249 Cvar_RegisterVariable (&gl_fogdensity);
4250 Cvar_RegisterVariable (&gl_fogred);
4251 Cvar_RegisterVariable (&gl_foggreen);
4252 Cvar_RegisterVariable (&gl_fogblue);
4253 Cvar_RegisterVariable (&gl_fogstart);
4254 Cvar_RegisterVariable (&gl_fogend);
4255 Cvar_RegisterVariable (&gl_skyclip);
4257 Cvar_RegisterVariable(&r_motionblur);
4258 Cvar_RegisterVariable(&r_damageblur);
4259 Cvar_RegisterVariable(&r_motionblur_averaging);
4260 Cvar_RegisterVariable(&r_motionblur_randomize);
4261 Cvar_RegisterVariable(&r_motionblur_minblur);
4262 Cvar_RegisterVariable(&r_motionblur_maxblur);
4263 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4264 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4265 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4266 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4267 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4268 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4269 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4270 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4271 Cvar_RegisterVariable(&r_equalize_entities_by);
4272 Cvar_RegisterVariable(&r_equalize_entities_to);
4273 Cvar_RegisterVariable(&r_depthfirst);
4274 Cvar_RegisterVariable(&r_useinfinitefarclip);
4275 Cvar_RegisterVariable(&r_farclip_base);
4276 Cvar_RegisterVariable(&r_farclip_world);
4277 Cvar_RegisterVariable(&r_nearclip);
4278 Cvar_RegisterVariable(&r_deformvertexes);
4279 Cvar_RegisterVariable(&r_transparent);
4280 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4281 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4282 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4283 Cvar_RegisterVariable(&r_showoverdraw);
4284 Cvar_RegisterVariable(&r_showbboxes);
4285 Cvar_RegisterVariable(&r_showsurfaces);
4286 Cvar_RegisterVariable(&r_showtris);
4287 Cvar_RegisterVariable(&r_shownormals);
4288 Cvar_RegisterVariable(&r_showlighting);
4289 Cvar_RegisterVariable(&r_showshadowvolumes);
4290 Cvar_RegisterVariable(&r_showcollisionbrushes);
4291 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4292 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4293 Cvar_RegisterVariable(&r_showdisabledepthtest);
4294 Cvar_RegisterVariable(&r_drawportals);
4295 Cvar_RegisterVariable(&r_drawentities);
4296 Cvar_RegisterVariable(&r_draw2d);
4297 Cvar_RegisterVariable(&r_drawworld);
4298 Cvar_RegisterVariable(&r_cullentities_trace);
4299 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4300 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4301 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4302 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4303 Cvar_RegisterVariable(&r_sortentities);
4304 Cvar_RegisterVariable(&r_drawviewmodel);
4305 Cvar_RegisterVariable(&r_drawexteriormodel);
4306 Cvar_RegisterVariable(&r_speeds);
4307 Cvar_RegisterVariable(&r_fullbrights);
4308 Cvar_RegisterVariable(&r_wateralpha);
4309 Cvar_RegisterVariable(&r_dynamic);
4310 Cvar_RegisterVariable(&r_fakelight);
4311 Cvar_RegisterVariable(&r_fakelight_intensity);
4312 Cvar_RegisterVariable(&r_fullbright);
4313 Cvar_RegisterVariable(&r_shadows);
4314 Cvar_RegisterVariable(&r_shadows_darken);
4315 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4316 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4317 Cvar_RegisterVariable(&r_shadows_throwdistance);
4318 Cvar_RegisterVariable(&r_shadows_throwdirection);
4319 Cvar_RegisterVariable(&r_shadows_focus);
4320 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4321 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4322 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4323 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4324 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4325 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4326 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4327 Cvar_RegisterVariable(&r_fog_exp2);
4328 Cvar_RegisterVariable(&r_fog_clear);
4329 Cvar_RegisterVariable(&r_drawfog);
4330 Cvar_RegisterVariable(&r_transparentdepthmasking);
4331 Cvar_RegisterVariable(&r_transparent_sortmindist);
4332 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4333 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4334 Cvar_RegisterVariable(&r_texture_dds_load);
4335 Cvar_RegisterVariable(&r_texture_dds_save);
4336 Cvar_RegisterVariable(&r_textureunits);
4337 Cvar_RegisterVariable(&gl_combine);
4338 Cvar_RegisterVariable(&r_usedepthtextures);
4339 Cvar_RegisterVariable(&r_viewfbo);
4340 Cvar_RegisterVariable(&r_viewscale);
4341 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4342 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4343 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4344 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4345 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4346 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4347 Cvar_RegisterVariable(&r_glsl);
4348 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4349 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4350 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4351 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4352 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4353 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4354 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4355 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4356 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4357 Cvar_RegisterVariable(&r_glsl_postprocess);
4358 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4359 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4360 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4361 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4362 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4363 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4364 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4365 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4366 Cvar_RegisterVariable(&r_celshading);
4367 Cvar_RegisterVariable(&r_celoutlines);
4369 Cvar_RegisterVariable(&r_water);
4370 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4371 Cvar_RegisterVariable(&r_water_clippingplanebias);
4372 Cvar_RegisterVariable(&r_water_refractdistort);
4373 Cvar_RegisterVariable(&r_water_reflectdistort);
4374 Cvar_RegisterVariable(&r_water_scissormode);
4375 Cvar_RegisterVariable(&r_water_lowquality);
4376 Cvar_RegisterVariable(&r_water_hideplayer);
4377 Cvar_RegisterVariable(&r_water_fbo);
4379 Cvar_RegisterVariable(&r_lerpsprites);
4380 Cvar_RegisterVariable(&r_lerpmodels);
4381 Cvar_RegisterVariable(&r_lerplightstyles);
4382 Cvar_RegisterVariable(&r_waterscroll);
4383 Cvar_RegisterVariable(&r_bloom);
4384 Cvar_RegisterVariable(&r_bloom_colorscale);
4385 Cvar_RegisterVariable(&r_bloom_brighten);
4386 Cvar_RegisterVariable(&r_bloom_blur);
4387 Cvar_RegisterVariable(&r_bloom_resolution);
4388 Cvar_RegisterVariable(&r_bloom_colorexponent);
4389 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4390 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4391 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4392 Cvar_RegisterVariable(&r_hdr_glowintensity);
4393 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4394 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4395 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4396 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4397 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4398 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4399 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4400 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4401 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4402 Cvar_RegisterVariable(&developer_texturelogging);
4403 Cvar_RegisterVariable(&gl_lightmaps);
4404 Cvar_RegisterVariable(&r_test);
4405 Cvar_RegisterVariable(&r_batch_multidraw);
4406 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4407 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4408 Cvar_RegisterVariable(&r_glsl_skeletal);
4409 Cvar_RegisterVariable(&r_glsl_saturation);
4410 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4411 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4412 Cvar_RegisterVariable(&r_framedatasize);
4413 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4414 Cvar_RegisterVariable(&r_buffermegs[i]);
4415 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4416 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4417 Cvar_SetValue("r_fullbrights", 0);
4418 #ifdef DP_MOBILETOUCH
4419 // GLES devices have terrible depth precision in general, so...
4420 Cvar_SetValueQuick(&r_nearclip, 4);
4421 Cvar_SetValueQuick(&r_farclip_base, 4096);
4422 Cvar_SetValueQuick(&r_farclip_world, 0);
4423 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4425 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4428 void Render_Init(void)
4441 R_LightningBeams_Init();
4451 extern char *ENGINE_EXTENSIONS;
4454 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4455 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4456 gl_version = (const char *)qglGetString(GL_VERSION);
4457 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4461 if (!gl_platformextensions)
4462 gl_platformextensions = "";
4464 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4465 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4466 Con_Printf("GL_VERSION: %s\n", gl_version);
4467 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4468 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4470 VID_CheckExtensions();
4472 // LordHavoc: report supported extensions
4474 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4476 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4479 // clear to black (loading plaque will be seen over this)
4480 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4484 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4488 if (r_trippy.integer)
4490 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4492 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4495 p = r_refdef.view.frustum + i;
4500 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4504 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4508 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4512 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4516 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4520 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4524 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4528 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4536 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4540 if (r_trippy.integer)
4542 for (i = 0;i < numplanes;i++)
4549 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4553 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4557 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4561 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4565 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4569 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4573 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4577 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4585 //==================================================================================
4587 // LordHavoc: this stores temporary data used within the same frame
4589 typedef struct r_framedata_mem_s
4591 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4592 size_t size; // how much usable space
4593 size_t current; // how much space in use
4594 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4595 size_t wantedsize; // how much space was allocated
4596 unsigned char *data; // start of real data (16byte aligned)
4600 static r_framedata_mem_t *r_framedata_mem;
4602 void R_FrameData_Reset(void)
4604 while (r_framedata_mem)
4606 r_framedata_mem_t *next = r_framedata_mem->purge;
4607 Mem_Free(r_framedata_mem);
4608 r_framedata_mem = next;
4612 static void R_FrameData_Resize(qboolean mustgrow)
4615 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4616 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4617 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4619 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4620 newmem->wantedsize = wantedsize;
4621 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4622 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4623 newmem->current = 0;
4625 newmem->purge = r_framedata_mem;
4626 r_framedata_mem = newmem;
4630 void R_FrameData_NewFrame(void)
4632 R_FrameData_Resize(false);
4633 if (!r_framedata_mem)
4635 // if we ran out of space on the last frame, free the old memory now
4636 while (r_framedata_mem->purge)
4638 // repeatedly remove the second item in the list, leaving only head
4639 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4640 Mem_Free(r_framedata_mem->purge);
4641 r_framedata_mem->purge = next;
4643 // reset the current mem pointer
4644 r_framedata_mem->current = 0;
4645 r_framedata_mem->mark = 0;
4648 void *R_FrameData_Alloc(size_t size)
4653 // align to 16 byte boundary - the data pointer is already aligned, so we
4654 // only need to ensure the size of every allocation is also aligned
4655 size = (size + 15) & ~15;
4657 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4659 // emergency - we ran out of space, allocate more memory
4660 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4661 // this might not be a growing it, but we'll allocate another buffer every time
4662 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4663 R_FrameData_Resize(true);
4666 data = r_framedata_mem->data + r_framedata_mem->current;
4667 r_framedata_mem->current += size;
4669 // count the usage for stats
4670 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4671 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4673 return (void *)data;
4676 void *R_FrameData_Store(size_t size, void *data)
4678 void *d = R_FrameData_Alloc(size);
4680 memcpy(d, data, size);
4684 void R_FrameData_SetMark(void)
4686 if (!r_framedata_mem)
4688 r_framedata_mem->mark = r_framedata_mem->current;
4691 void R_FrameData_ReturnToMark(void)
4693 if (!r_framedata_mem)
4695 r_framedata_mem->current = r_framedata_mem->mark;
4698 //==================================================================================
4700 // avoid reusing the same buffer objects on consecutive frames
4701 #define R_BUFFERDATA_CYCLE 3
4703 typedef struct r_bufferdata_buffer_s
4705 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4706 size_t size; // how much usable space
4707 size_t current; // how much space in use
4708 r_meshbuffer_t *buffer; // the buffer itself
4710 r_bufferdata_buffer_t;
4712 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4713 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4715 /// frees all dynamic buffers
4716 void R_BufferData_Reset(void)
4719 r_bufferdata_buffer_t **p, *mem;
4720 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4722 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4725 p = &r_bufferdata_buffer[cycle][type];
4731 R_Mesh_DestroyMeshBuffer(mem->buffer);
4738 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4739 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4741 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4743 float newvalue = r_buffermegs[type].value;
4745 // increase the cvar if we have to (but only if we already have a mem)
4746 if (mustgrow && mem)
4748 newvalue = bound(0.25f, newvalue, 256.0f);
4749 while (newvalue * 1024*1024 < minsize)
4752 // clamp the cvar to valid range
4753 newvalue = bound(0.25f, newvalue, 256.0f);
4754 if (r_buffermegs[type].value != newvalue)
4755 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4757 // calculate size in bytes
4758 size = (size_t)(newvalue * 1024*1024);
4759 size = bound(131072, size, 256*1024*1024);
4761 // allocate a new buffer if the size is different (purge old one later)
4762 // or if we were told we must grow the buffer
4763 if (!mem || mem->size != size || mustgrow)
4765 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4768 if (type == R_BUFFERDATA_VERTEX)
4769 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4770 else if (type == R_BUFFERDATA_INDEX16)
4771 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4772 else if (type == R_BUFFERDATA_INDEX32)
4773 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4774 else if (type == R_BUFFERDATA_UNIFORM)
4775 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4776 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4777 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4781 void R_BufferData_NewFrame(void)
4784 r_bufferdata_buffer_t **p, *mem;
4785 // cycle to the next frame's buffers
4786 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4787 // if we ran out of space on the last time we used these buffers, free the old memory now
4788 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4790 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4792 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4793 // free all but the head buffer, this is how we recycle obsolete
4794 // buffers after they are no longer in use
4795 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4801 R_Mesh_DestroyMeshBuffer(mem->buffer);
4804 // reset the current offset
4805 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4810 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4812 r_bufferdata_buffer_t *mem;
4816 *returnbufferoffset = 0;
4818 // align size to a byte boundary appropriate for the buffer type, this
4819 // makes all allocations have aligned start offsets
4820 if (type == R_BUFFERDATA_UNIFORM)
4821 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4823 padsize = (datasize + 15) & ~15;
4825 // if we ran out of space in this buffer we must allocate a new one
4826 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4827 R_BufferData_Resize(type, true, padsize);
4829 // if the resize did not give us enough memory, fail
4830 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4831 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4833 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4834 offset = mem->current;
4835 mem->current += padsize;
4837 // upload the data to the buffer at the chosen offset
4839 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4840 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4842 // count the usage for stats
4843 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4844 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4846 // return the buffer offset
4847 *returnbufferoffset = offset;
4852 //==================================================================================
4854 // LordHavoc: animcache originally written by Echon, rewritten since then
4857 * Animation cache prevents re-generating mesh data for an animated model
4858 * multiple times in one frame for lighting, shadowing, reflections, etc.
4861 void R_AnimCache_Free(void)
4865 void R_AnimCache_ClearCache(void)
4868 entity_render_t *ent;
4870 for (i = 0;i < r_refdef.scene.numentities;i++)
4872 ent = r_refdef.scene.entities[i];
4873 ent->animcache_vertex3f = NULL;
4874 ent->animcache_vertex3f_vertexbuffer = NULL;
4875 ent->animcache_vertex3f_bufferoffset = 0;
4876 ent->animcache_normal3f = NULL;
4877 ent->animcache_normal3f_vertexbuffer = NULL;
4878 ent->animcache_normal3f_bufferoffset = 0;
4879 ent->animcache_svector3f = NULL;
4880 ent->animcache_svector3f_vertexbuffer = NULL;
4881 ent->animcache_svector3f_bufferoffset = 0;
4882 ent->animcache_tvector3f = NULL;
4883 ent->animcache_tvector3f_vertexbuffer = NULL;
4884 ent->animcache_tvector3f_bufferoffset = 0;
4885 ent->animcache_vertexmesh = NULL;
4886 ent->animcache_vertexmesh_vertexbuffer = NULL;
4887 ent->animcache_vertexmesh_bufferoffset = 0;
4888 ent->animcache_skeletaltransform3x4 = NULL;
4889 ent->animcache_skeletaltransform3x4buffer = NULL;
4890 ent->animcache_skeletaltransform3x4offset = 0;
4891 ent->animcache_skeletaltransform3x4size = 0;
4895 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4899 // check if we need the meshbuffers
4900 if (!vid.useinterleavedarrays)
4903 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4904 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4905 // TODO: upload vertexbuffer?
4906 if (ent->animcache_vertexmesh)
4908 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4909 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4910 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4911 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4912 for (i = 0;i < numvertices;i++)
4913 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4914 if (ent->animcache_svector3f)
4915 for (i = 0;i < numvertices;i++)
4916 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4917 if (ent->animcache_tvector3f)
4918 for (i = 0;i < numvertices;i++)
4919 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4920 if (ent->animcache_normal3f)
4921 for (i = 0;i < numvertices;i++)
4922 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4926 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4928 dp_model_t *model = ent->model;
4931 // see if this ent is worth caching
4932 if (!model || !model->Draw || !model->AnimateVertices)
4934 // nothing to cache if it contains no animations and has no skeleton
4935 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4937 // see if it is already cached for gpuskeletal
4938 if (ent->animcache_skeletaltransform3x4)
4940 // see if it is already cached as a mesh
4941 if (ent->animcache_vertex3f)
4943 // check if we need to add normals or tangents
4944 if (ent->animcache_normal3f)
4945 wantnormals = false;
4946 if (ent->animcache_svector3f)
4947 wanttangents = false;
4948 if (!wantnormals && !wanttangents)
4952 // check which kind of cache we need to generate
4953 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4955 // cache the skeleton so the vertex shader can use it
4956 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4957 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4958 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4959 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4960 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4961 // note: this can fail if the buffer is at the grow limit
4962 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4963 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4965 else if (ent->animcache_vertex3f)
4967 // mesh was already cached but we may need to add normals/tangents
4968 // (this only happens with multiple views, reflections, cameras, etc)
4969 if (wantnormals || wanttangents)
4971 numvertices = model->surfmesh.num_vertices;
4973 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4976 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4977 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4979 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4980 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4981 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4982 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4983 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4988 // generate mesh cache
4989 numvertices = model->surfmesh.num_vertices;
4990 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4992 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4995 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4996 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4998 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4999 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5000 if (wantnormals || wanttangents)
5002 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5003 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5004 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5006 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5007 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5008 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5013 void R_AnimCache_CacheVisibleEntities(void)
5016 qboolean wantnormals = true;
5017 qboolean wanttangents = !r_showsurfaces.integer;
5019 switch(vid.renderpath)
5021 case RENDERPATH_GL20:
5022 case RENDERPATH_D3D9:
5023 case RENDERPATH_D3D10:
5024 case RENDERPATH_D3D11:
5025 case RENDERPATH_GLES2:
5027 case RENDERPATH_GL11:
5028 case RENDERPATH_GL13:
5029 case RENDERPATH_GLES1:
5030 wanttangents = false;
5032 case RENDERPATH_SOFT:
5036 if (r_shownormals.integer)
5037 wanttangents = wantnormals = true;
5039 // TODO: thread this
5040 // NOTE: R_PrepareRTLights() also caches entities
5042 for (i = 0;i < r_refdef.scene.numentities;i++)
5043 if (r_refdef.viewcache.entityvisible[i])
5044 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5047 //==================================================================================
5049 extern cvar_t r_overheadsprites_pushback;
5051 static void R_View_UpdateEntityLighting (void)
5054 entity_render_t *ent;
5055 vec3_t tempdiffusenormal, avg;
5056 vec_t f, fa, fd, fdd;
5057 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5059 for (i = 0;i < r_refdef.scene.numentities;i++)
5061 ent = r_refdef.scene.entities[i];
5063 // skip unseen models
5064 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5068 if (ent->model && ent->model == cl.worldmodel)
5070 // TODO: use modellight for r_ambient settings on world?
5071 VectorSet(ent->modellight_ambient, 0, 0, 0);
5072 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5073 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5077 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5079 // aleady updated by CSQC
5080 // TODO: force modellight on BSP models in this case?
5081 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5085 // fetch the lighting from the worldmodel data
5086 VectorClear(ent->modellight_ambient);
5087 VectorClear(ent->modellight_diffuse);
5088 VectorClear(tempdiffusenormal);
5089 if (ent->flags & RENDER_LIGHT)
5092 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5094 // complete lightning for lit sprites
5095 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5096 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5098 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5099 org[2] = org[2] + r_overheadsprites_pushback.value;
5100 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5103 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5105 if(ent->flags & RENDER_EQUALIZE)
5107 // first fix up ambient lighting...
5108 if(r_equalize_entities_minambient.value > 0)
5110 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5113 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5114 if(fa < r_equalize_entities_minambient.value * fd)
5117 // fa'/fd' = minambient
5118 // fa'+0.25*fd' = fa+0.25*fd
5120 // fa' = fd' * minambient
5121 // fd'*(0.25+minambient) = fa+0.25*fd
5123 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5124 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5126 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5127 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
5128 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5129 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5134 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5136 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5137 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5141 // adjust brightness and saturation to target
5142 avg[0] = avg[1] = avg[2] = fa / f;
5143 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5144 avg[0] = avg[1] = avg[2] = fd / f;
5145 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5151 VectorSet(ent->modellight_ambient, 1, 1, 1);
5154 // move the light direction into modelspace coordinates for lighting code
5155 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5156 if(VectorLength2(ent->modellight_lightdir) == 0)
5157 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5158 VectorNormalize(ent->modellight_lightdir);
5162 #define MAX_LINEOFSIGHTTRACES 64
5164 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5167 vec3_t boxmins, boxmaxs;
5170 dp_model_t *model = r_refdef.scene.worldmodel;
5172 if (!model || !model->brush.TraceLineOfSight)
5175 // expand the box a little
5176 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5177 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5178 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5179 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5180 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5181 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5183 // return true if eye is inside enlarged box
5184 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5188 VectorCopy(eye, start);
5189 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5190 if (model->brush.TraceLineOfSight(model, start, end))
5193 // try various random positions
5194 for (i = 0;i < numsamples;i++)
5196 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5197 if (model->brush.TraceLineOfSight(model, start, end))
5205 static void R_View_UpdateEntityVisible (void)
5210 entity_render_t *ent;
5212 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5213 : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5214 : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL
5215 : RENDER_EXTERIORMODEL;
5216 if (!r_drawviewmodel.integer)
5217 renderimask |= RENDER_VIEWMODEL;
5218 if (!r_drawexteriormodel.integer)
5219 renderimask |= RENDER_EXTERIORMODEL;
5220 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5222 // worldmodel can check visibility
5223 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5224 for (i = 0;i < r_refdef.scene.numentities;i++)
5226 ent = r_refdef.scene.entities[i];
5227 if (!(ent->flags & renderimask))
5228 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
5229 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
5230 r_refdef.viewcache.entityvisible[i] = true;
5235 // no worldmodel or it can't check visibility
5236 for (i = 0;i < r_refdef.scene.numentities;i++)
5238 ent = r_refdef.scene.entities[i];
5239 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
5242 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5243 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5245 for (i = 0;i < r_refdef.scene.numentities;i++)
5247 if (!r_refdef.viewcache.entityvisible[i])
5249 ent = r_refdef.scene.entities[i];
5250 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5252 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5254 continue; // temp entities do pvs only
5255 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5256 ent->last_trace_visibility = realtime;
5257 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5258 r_refdef.viewcache.entityvisible[i] = 0;
5264 /// only used if skyrendermasked, and normally returns false
5265 static int R_DrawBrushModelsSky (void)
5268 entity_render_t *ent;
5271 for (i = 0;i < r_refdef.scene.numentities;i++)
5273 if (!r_refdef.viewcache.entityvisible[i])
5275 ent = r_refdef.scene.entities[i];
5276 if (!ent->model || !ent->model->DrawSky)
5278 ent->model->DrawSky(ent);
5284 static void R_DrawNoModel(entity_render_t *ent);
5285 static void R_DrawModels(void)
5288 entity_render_t *ent;
5290 for (i = 0;i < r_refdef.scene.numentities;i++)
5292 if (!r_refdef.viewcache.entityvisible[i])
5294 ent = r_refdef.scene.entities[i];
5295 r_refdef.stats[r_stat_entities]++;
5297 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5300 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5301 Con_Printf("R_DrawModels\n");
5302 Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
5303 Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
5304 Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
5307 if (ent->model && ent->model->Draw != NULL)
5308 ent->model->Draw(ent);
5314 static void R_DrawModelsDepth(void)
5317 entity_render_t *ent;
5319 for (i = 0;i < r_refdef.scene.numentities;i++)
5321 if (!r_refdef.viewcache.entityvisible[i])
5323 ent = r_refdef.scene.entities[i];
5324 if (ent->model && ent->model->DrawDepth != NULL)
5325 ent->model->DrawDepth(ent);
5329 static void R_DrawModelsDebug(void)
5332 entity_render_t *ent;
5334 for (i = 0;i < r_refdef.scene.numentities;i++)
5336 if (!r_refdef.viewcache.entityvisible[i])
5338 ent = r_refdef.scene.entities[i];
5339 if (ent->model && ent->model->DrawDebug != NULL)
5340 ent->model->DrawDebug(ent);
5344 static void R_DrawModelsAddWaterPlanes(void)
5347 entity_render_t *ent;
5349 for (i = 0;i < r_refdef.scene.numentities;i++)
5351 if (!r_refdef.viewcache.entityvisible[i])
5353 ent = r_refdef.scene.entities[i];
5354 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5355 ent->model->DrawAddWaterPlanes(ent);
5359 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5361 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5363 if (r_hdr_irisadaptation.integer)
5368 vec3_t diffusenormal;
5370 vec_t brightness = 0.0f;
5375 VectorCopy(r_refdef.view.forward, forward);
5376 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5378 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5379 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5380 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5381 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5382 d = DotProduct(forward, diffusenormal);
5383 brightness += VectorLength(ambient);
5385 brightness += d * VectorLength(diffuse);
5387 brightness *= 1.0f / c;
5388 brightness += 0.00001f; // make sure it's never zero
5389 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5390 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5391 current = r_hdr_irisadaptation_value.value;
5393 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5394 else if (current > goal)
5395 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5396 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5397 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5399 else if (r_hdr_irisadaptation_value.value != 1.0f)
5400 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5403 static void R_View_SetFrustum(const int *scissor)
5406 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5407 vec3_t forward, left, up, origin, v;
5411 // flipped x coordinates (because x points left here)
5412 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5413 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5415 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5416 switch(vid.renderpath)
5418 case RENDERPATH_D3D9:
5419 case RENDERPATH_D3D10:
5420 case RENDERPATH_D3D11:
5421 // non-flipped y coordinates
5422 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5423 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5425 case RENDERPATH_SOFT:
5426 case RENDERPATH_GL11:
5427 case RENDERPATH_GL13:
5428 case RENDERPATH_GL20:
5429 case RENDERPATH_GLES1:
5430 case RENDERPATH_GLES2:
5431 // non-flipped y coordinates
5432 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5433 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5438 // we can't trust r_refdef.view.forward and friends in reflected scenes
5439 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5442 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5443 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5444 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5445 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5446 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5447 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5448 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5449 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5450 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5451 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5452 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5453 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5457 zNear = r_refdef.nearclip;
5458 nudge = 1.0 - 1.0 / (1<<23);
5459 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5460 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5461 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5462 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5463 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5464 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5465 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5466 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5472 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5473 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5474 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5475 r_refdef.view.frustum[0].dist = m[15] - m[12];
5477 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5478 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5479 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5480 r_refdef.view.frustum[1].dist = m[15] + m[12];
5482 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5483 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5484 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5485 r_refdef.view.frustum[2].dist = m[15] - m[13];
5487 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5488 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5489 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5490 r_refdef.view.frustum[3].dist = m[15] + m[13];
5492 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5493 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5494 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5495 r_refdef.view.frustum[4].dist = m[15] - m[14];
5497 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5498 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5499 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5500 r_refdef.view.frustum[5].dist = m[15] + m[14];
5503 if (r_refdef.view.useperspective)
5505 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5506 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5507 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5508 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5509 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5511 // then the normals from the corners relative to origin
5512 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5513 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5514 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5515 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5517 // in a NORMAL view, forward cross left == up
5518 // in a REFLECTED view, forward cross left == down
5519 // so our cross products above need to be adjusted for a left handed coordinate system
5520 CrossProduct(forward, left, v);
5521 if(DotProduct(v, up) < 0)
5523 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5524 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5525 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5526 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5529 // Leaving those out was a mistake, those were in the old code, and they
5530 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5531 // I couldn't reproduce it after adding those normalizations. --blub
5532 VectorNormalize(r_refdef.view.frustum[0].normal);
5533 VectorNormalize(r_refdef.view.frustum[1].normal);
5534 VectorNormalize(r_refdef.view.frustum[2].normal);
5535 VectorNormalize(r_refdef.view.frustum[3].normal);
5537 // make the corners absolute
5538 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5539 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5540 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5541 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5544 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5546 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5547 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5548 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5549 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5550 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5554 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5555 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5556 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5557 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5558 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5559 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5560 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5561 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5562 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5563 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5565 r_refdef.view.numfrustumplanes = 5;
5567 if (r_refdef.view.useclipplane)
5569 r_refdef.view.numfrustumplanes = 6;
5570 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5573 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5574 PlaneClassify(r_refdef.view.frustum + i);
5576 // LordHavoc: note to all quake engine coders, Quake had a special case
5577 // for 90 degrees which assumed a square view (wrong), so I removed it,
5578 // Quake2 has it disabled as well.
5580 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5581 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5582 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5583 //PlaneClassify(&frustum[0]);
5585 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5586 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5587 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5588 //PlaneClassify(&frustum[1]);
5590 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5591 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5592 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5593 //PlaneClassify(&frustum[2]);
5595 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5596 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5597 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5598 //PlaneClassify(&frustum[3]);
5601 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5602 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5603 //PlaneClassify(&frustum[4]);
5606 static void R_View_UpdateWithScissor(const int *myscissor)
5608 R_Main_ResizeViewCache();
5609 R_View_SetFrustum(myscissor);
5610 R_View_WorldVisibility(r_refdef.view.useclipplane);
5611 R_View_UpdateEntityVisible();
5612 R_View_UpdateEntityLighting();
5615 static void R_View_Update(void)
5617 R_Main_ResizeViewCache();
5618 R_View_SetFrustum(NULL);
5619 R_View_WorldVisibility(r_refdef.view.useclipplane);
5620 R_View_UpdateEntityVisible();
5621 R_View_UpdateEntityLighting();
5624 float viewscalefpsadjusted = 1.0f;
5626 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5628 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5629 scale = bound(0.03125f, scale, 1.0f);
5630 *outwidth = (int)ceil(width * scale);
5631 *outheight = (int)ceil(height * scale);
5634 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5636 const float *customclipplane = NULL;
5638 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5639 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5641 // LordHavoc: couldn't figure out how to make this approach the
5642 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5643 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5644 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5645 dist = r_refdef.view.clipplane.dist;
5646 plane[0] = r_refdef.view.clipplane.normal[0];
5647 plane[1] = r_refdef.view.clipplane.normal[1];
5648 plane[2] = r_refdef.view.clipplane.normal[2];
5650 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5653 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5654 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5656 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5657 if (!r_refdef.view.useperspective)
5658 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5659 else if (vid.stencil && r_useinfinitefarclip.integer)
5660 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5662 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5663 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5664 R_SetViewport(&r_refdef.view.viewport);
5665 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5667 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5668 float screenplane[4];
5669 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5670 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5671 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5672 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5673 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5677 void R_EntityMatrix(const matrix4x4_t *matrix)
5679 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5681 gl_modelmatrixchanged = false;
5682 gl_modelmatrix = *matrix;
5683 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5684 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5685 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5686 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5688 switch(vid.renderpath)
5690 case RENDERPATH_D3D9:
5692 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5693 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5696 case RENDERPATH_D3D10:
5697 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5699 case RENDERPATH_D3D11:
5700 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5702 case RENDERPATH_GL11:
5703 case RENDERPATH_GL13:
5704 case RENDERPATH_GLES1:
5706 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5709 case RENDERPATH_SOFT:
5710 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5711 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5713 case RENDERPATH_GL20:
5714 case RENDERPATH_GLES2:
5715 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5716 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5722 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5724 r_viewport_t viewport;
5728 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5729 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
5730 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5731 R_SetViewport(&viewport);
5732 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5733 GL_Color(1, 1, 1, 1);
5734 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5735 GL_BlendFunc(GL_ONE, GL_ZERO);
5736 GL_ScissorTest(false);
5737 GL_DepthMask(false);
5738 GL_DepthRange(0, 1);
5739 GL_DepthTest(false);
5740 GL_DepthFunc(GL_LEQUAL);
5741 R_EntityMatrix(&identitymatrix);
5742 R_Mesh_ResetTextureState();
5743 GL_PolygonOffset(0, 0);
5744 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5745 switch(vid.renderpath)
5747 case RENDERPATH_GL11:
5748 case RENDERPATH_GL13:
5749 case RENDERPATH_GL20:
5750 case RENDERPATH_GLES1:
5751 case RENDERPATH_GLES2:
5752 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5754 case RENDERPATH_D3D9:
5755 case RENDERPATH_D3D10:
5756 case RENDERPATH_D3D11:
5757 case RENDERPATH_SOFT:
5760 GL_CullFace(GL_NONE);
5765 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5769 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5772 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5776 R_SetupView(true, fbo, depthtexture, colortexture);
5777 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5778 GL_Color(1, 1, 1, 1);
5779 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5780 GL_BlendFunc(GL_ONE, GL_ZERO);
5781 GL_ScissorTest(true);
5783 GL_DepthRange(0, 1);
5785 GL_DepthFunc(GL_LEQUAL);
5786 R_EntityMatrix(&identitymatrix);
5787 R_Mesh_ResetTextureState();
5788 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5789 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5790 switch(vid.renderpath)
5792 case RENDERPATH_GL11:
5793 case RENDERPATH_GL13:
5794 case RENDERPATH_GL20:
5795 case RENDERPATH_GLES1:
5796 case RENDERPATH_GLES2:
5797 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5799 case RENDERPATH_D3D9:
5800 case RENDERPATH_D3D10:
5801 case RENDERPATH_D3D11:
5802 case RENDERPATH_SOFT:
5805 GL_CullFace(r_refdef.view.cullface_back);
5810 R_RenderView_UpdateViewVectors
5813 void R_RenderView_UpdateViewVectors(void)
5815 // break apart the view matrix into vectors for various purposes
5816 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5817 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5818 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5819 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5820 // make an inverted copy of the view matrix for tracking sprites
5821 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5824 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5825 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5827 static void R_Water_StartFrame(void)
5830 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5831 r_waterstate_waterplane_t *p;
5832 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5834 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5837 switch(vid.renderpath)
5839 case RENDERPATH_GL20:
5840 case RENDERPATH_D3D9:
5841 case RENDERPATH_D3D10:
5842 case RENDERPATH_D3D11:
5843 case RENDERPATH_SOFT:
5844 case RENDERPATH_GLES2:
5846 case RENDERPATH_GL11:
5847 case RENDERPATH_GL13:
5848 case RENDERPATH_GLES1:
5852 // set waterwidth and waterheight to the water resolution that will be
5853 // used (often less than the screen resolution for faster rendering)
5854 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5856 // calculate desired texture sizes
5857 // can't use water if the card does not support the texture size
5858 if (!r_water.integer || r_showsurfaces.integer)
5859 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5860 else if (vid.support.arb_texture_non_power_of_two)
5862 texturewidth = waterwidth;
5863 textureheight = waterheight;
5864 camerawidth = waterwidth;
5865 cameraheight = waterheight;
5869 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5870 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5871 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5872 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5875 // allocate textures as needed
5876 if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5878 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5879 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5881 if (p->texture_refraction)
5882 R_FreeTexture(p->texture_refraction);
5883 p->texture_refraction = NULL;
5884 if (p->fbo_refraction)
5885 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5886 p->fbo_refraction = 0;
5887 if (p->texture_reflection)
5888 R_FreeTexture(p->texture_reflection);
5889 p->texture_reflection = NULL;
5890 if (p->fbo_reflection)
5891 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5892 p->fbo_reflection = 0;
5893 if (p->texture_camera)
5894 R_FreeTexture(p->texture_camera);
5895 p->texture_camera = NULL;
5897 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5900 memset(&r_fb.water, 0, sizeof(r_fb.water));
5901 r_fb.water.texturewidth = texturewidth;
5902 r_fb.water.textureheight = textureheight;
5903 r_fb.water.camerawidth = camerawidth;
5904 r_fb.water.cameraheight = cameraheight;
5907 if (r_fb.water.texturewidth)
5909 int scaledwidth, scaledheight;
5911 r_fb.water.enabled = true;
5913 // water resolution is usually reduced
5914 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5915 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5916 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5918 // set up variables that will be used in shader setup
5919 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5920 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5921 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5922 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5925 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5926 r_fb.water.numwaterplanes = 0;
5929 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5931 int planeindex, bestplaneindex, vertexindex;
5932 vec3_t mins, maxs, normal, center, v, n;
5933 vec_t planescore, bestplanescore;
5935 r_waterstate_waterplane_t *p;
5936 texture_t *t = R_GetCurrentTexture(surface->texture);
5938 rsurface.texture = t;
5939 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5940 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5941 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5943 // average the vertex normals, find the surface bounds (after deformvertexes)
5944 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5945 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5946 VectorCopy(n, normal);
5947 VectorCopy(v, mins);
5948 VectorCopy(v, maxs);
5949 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5951 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5952 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5953 VectorAdd(normal, n, normal);
5954 mins[0] = min(mins[0], v[0]);
5955 mins[1] = min(mins[1], v[1]);
5956 mins[2] = min(mins[2], v[2]);
5957 maxs[0] = max(maxs[0], v[0]);
5958 maxs[1] = max(maxs[1], v[1]);
5959 maxs[2] = max(maxs[2], v[2]);
5961 VectorNormalize(normal);
5962 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5964 VectorCopy(normal, plane.normal);
5965 VectorNormalize(plane.normal);
5966 plane.dist = DotProduct(center, plane.normal);
5967 PlaneClassify(&plane);
5968 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5970 // skip backfaces (except if nocullface is set)
5971 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5973 VectorNegate(plane.normal, plane.normal);
5975 PlaneClassify(&plane);
5979 // find a matching plane if there is one
5980 bestplaneindex = -1;
5981 bestplanescore = 1048576.0f;
5982 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5984 if(p->camera_entity == t->camera_entity)
5986 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5987 if (bestplaneindex < 0 || bestplanescore > planescore)
5989 bestplaneindex = planeindex;
5990 bestplanescore = planescore;
5994 planeindex = bestplaneindex;
5995 p = r_fb.water.waterplanes + planeindex;
5997 // if this surface does not fit any known plane rendered this frame, add one
5998 if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6000 // store the new plane
6001 planeindex = r_fb.water.numwaterplanes++;
6002 p = r_fb.water.waterplanes + planeindex;
6004 // clear materialflags and pvs
6005 p->materialflags = 0;
6006 p->pvsvalid = false;
6007 p->camera_entity = t->camera_entity;
6008 VectorCopy(mins, p->mins);
6009 VectorCopy(maxs, p->maxs);
6013 // merge mins/maxs when we're adding this surface to the plane
6014 p->mins[0] = min(p->mins[0], mins[0]);
6015 p->mins[1] = min(p->mins[1], mins[1]);
6016 p->mins[2] = min(p->mins[2], mins[2]);
6017 p->maxs[0] = max(p->maxs[0], maxs[0]);
6018 p->maxs[1] = max(p->maxs[1], maxs[1]);
6019 p->maxs[2] = max(p->maxs[2], maxs[2]);
6021 // merge this surface's materialflags into the waterplane
6022 p->materialflags |= t->currentmaterialflags;
6023 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6025 // merge this surface's PVS into the waterplane
6026 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6027 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6029 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6035 extern cvar_t r_drawparticles;
6036 extern cvar_t r_drawdecals;
6038 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6041 r_refdef_view_t originalview;
6042 r_refdef_view_t myview;
6043 int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
6044 r_waterstate_waterplane_t *p;
6046 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6049 originalview = r_refdef.view;
6051 // lowquality hack, temporarily shut down some cvars and restore afterwards
6052 qualityreduction = r_water_lowquality.integer;
6053 if (qualityreduction > 0)
6055 if (qualityreduction >= 1)
6057 old_r_shadows = r_shadows.integer;
6058 old_r_worldrtlight = r_shadow_realtime_world.integer;
6059 old_r_dlight = r_shadow_realtime_dlight.integer;
6060 Cvar_SetValueQuick(&r_shadows, 0);
6061 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6062 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6064 if (qualityreduction >= 2)
6066 old_r_dynamic = r_dynamic.integer;
6067 old_r_particles = r_drawparticles.integer;
6068 old_r_decals = r_drawdecals.integer;
6069 Cvar_SetValueQuick(&r_dynamic, 0);
6070 Cvar_SetValueQuick(&r_drawparticles, 0);
6071 Cvar_SetValueQuick(&r_drawdecals, 0);
6075 // make sure enough textures are allocated
6076 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6078 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6080 if (!p->texture_refraction)
6081 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6082 if (!p->texture_refraction)
6086 if (r_fb.water.depthtexture == NULL)
6087 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6088 if (p->fbo_refraction == 0)
6089 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6092 else if (p->materialflags & MATERIALFLAG_CAMERA)
6094 if (!p->texture_camera)
6095 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
6096 if (!p->texture_camera)
6100 if (r_fb.water.depthtexture == NULL)
6101 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6102 if (p->fbo_camera == 0)
6103 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6107 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6109 if (!p->texture_reflection)
6110 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6111 if (!p->texture_reflection)
6115 if (r_fb.water.depthtexture == NULL)
6116 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6117 if (p->fbo_reflection == 0)
6118 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6124 r_refdef.view = originalview;
6125 r_refdef.view.showdebug = false;
6126 r_refdef.view.width = r_fb.water.waterwidth;
6127 r_refdef.view.height = r_fb.water.waterheight;
6128 r_refdef.view.useclipplane = true;
6129 myview = r_refdef.view;
6130 r_fb.water.renderingscene = true;
6131 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6133 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6135 r_refdef.view = myview;
6136 if(r_water_scissormode.integer)
6138 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6139 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6140 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6143 // render reflected scene and copy into texture
6144 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6145 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6146 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6147 r_refdef.view.clipplane = p->plane;
6148 // reverse the cullface settings for this render
6149 r_refdef.view.cullface_front = GL_FRONT;
6150 r_refdef.view.cullface_back = GL_BACK;
6151 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6153 r_refdef.view.usecustompvs = true;
6155 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6157 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6160 r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6161 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6162 R_ClearScreen(r_refdef.fogenabled);
6163 if(r_water_scissormode.integer & 2)
6164 R_View_UpdateWithScissor(myscissor);
6167 R_AnimCache_CacheVisibleEntities();
6168 if(r_water_scissormode.integer & 1)
6169 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6170 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6172 if (!p->fbo_reflection)
6173 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6174 r_fb.water.hideplayer = false;
6177 // render the normal view scene and copy into texture
6178 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
6179 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6181 r_refdef.view = myview;
6182 if(r_water_scissormode.integer)
6184 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6185 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6186 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6189 r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6191 r_refdef.view.clipplane = p->plane;
6192 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6193 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6195 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6197 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6198 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6199 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6200 R_RenderView_UpdateViewVectors();
6201 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6203 r_refdef.view.usecustompvs = true;
6204 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
6208 PlaneClassify(&r_refdef.view.clipplane);
6210 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6211 R_ClearScreen(r_refdef.fogenabled);
6212 if(r_water_scissormode.integer & 2)
6213 R_View_UpdateWithScissor(myscissor);
6216 R_AnimCache_CacheVisibleEntities();
6217 if(r_water_scissormode.integer & 1)
6218 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6219 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6221 if (!p->fbo_refraction)
6222 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6223 r_fb.water.hideplayer = false;
6225 else if (p->materialflags & MATERIALFLAG_CAMERA)
6227 r_refdef.view = myview;
6229 r_refdef.view.clipplane = p->plane;
6230 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6231 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6233 r_refdef.view.width = r_fb.water.camerawidth;
6234 r_refdef.view.height = r_fb.water.cameraheight;
6235 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6236 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6237 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6238 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6240 if(p->camera_entity)
6242 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6243 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6246 // note: all of the view is used for displaying... so
6247 // there is no use in scissoring
6249 // reverse the cullface settings for this render
6250 r_refdef.view.cullface_front = GL_FRONT;
6251 r_refdef.view.cullface_back = GL_BACK;
6252 // also reverse the view matrix
6253 Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
6254 R_RenderView_UpdateViewVectors();
6255 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6257 r_refdef.view.usecustompvs = true;
6258 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
6261 // camera needs no clipplane
6262 r_refdef.view.useclipplane = false;
6264 PlaneClassify(&r_refdef.view.clipplane);
6266 r_fb.water.hideplayer = false;
6268 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6269 R_ClearScreen(r_refdef.fogenabled);
6271 R_AnimCache_CacheVisibleEntities();
6272 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6275 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6276 r_fb.water.hideplayer = false;
6280 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6281 r_fb.water.renderingscene = false;
6282 r_refdef.view = originalview;
6283 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6284 if (!r_fb.water.depthtexture)
6285 R_ClearScreen(r_refdef.fogenabled);
6287 R_AnimCache_CacheVisibleEntities();
6290 r_refdef.view = originalview;
6291 r_fb.water.renderingscene = false;
6292 Cvar_SetValueQuick(&r_water, 0);
6293 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6295 // lowquality hack, restore cvars
6296 if (qualityreduction > 0)
6298 if (qualityreduction >= 1)
6300 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6301 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6302 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6304 if (qualityreduction >= 2)
6306 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6307 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6308 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6313 static void R_Bloom_StartFrame(void)
6316 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6317 int viewwidth, viewheight;
6318 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6319 textype_t textype = TEXTYPE_COLORBUFFER;
6321 switch (vid.renderpath)
6323 case RENDERPATH_GL20:
6324 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6325 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6327 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6328 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6331 case RENDERPATH_GL11:
6332 case RENDERPATH_GL13:
6333 case RENDERPATH_GLES1:
6334 case RENDERPATH_GLES2:
6335 case RENDERPATH_D3D9:
6336 case RENDERPATH_D3D10:
6337 case RENDERPATH_D3D11:
6338 r_fb.usedepthtextures = false;
6340 case RENDERPATH_SOFT:
6341 r_fb.usedepthtextures = true;
6345 if (r_viewscale_fpsscaling.integer)
6347 double actualframetime;
6348 double targetframetime;
6350 actualframetime = r_refdef.lastdrawscreentime;
6351 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6352 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6353 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6354 if (r_viewscale_fpsscaling_stepsize.value > 0)
6355 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6356 viewscalefpsadjusted += adjust;
6357 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6360 viewscalefpsadjusted = 1.0f;
6362 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6364 switch(vid.renderpath)
6366 case RENDERPATH_GL20:
6367 case RENDERPATH_D3D9:
6368 case RENDERPATH_D3D10:
6369 case RENDERPATH_D3D11:
6370 case RENDERPATH_SOFT:
6371 case RENDERPATH_GLES2:
6373 case RENDERPATH_GL11:
6374 case RENDERPATH_GL13:
6375 case RENDERPATH_GLES1:
6379 // set bloomwidth and bloomheight to the bloom resolution that will be
6380 // used (often less than the screen resolution for faster rendering)
6381 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6382 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6383 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6384 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6385 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6387 // calculate desired texture sizes
6388 if (vid.support.arb_texture_non_power_of_two)
6390 screentexturewidth = vid.width;
6391 screentextureheight = vid.height;
6392 bloomtexturewidth = r_fb.bloomwidth;
6393 bloomtextureheight = r_fb.bloomheight;
6397 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6398 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6399 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6400 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6403 if ((r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
6405 Cvar_SetValueQuick(&r_bloom, 0);
6406 Cvar_SetValueQuick(&r_motionblur, 0);
6407 Cvar_SetValueQuick(&r_damageblur, 0);
6410 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6412 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6414 && r_viewscale.value == 1.0f
6415 && !r_viewscale_fpsscaling.integer)
6416 screentexturewidth = screentextureheight = 0;
6417 if (!r_bloom.integer)
6418 bloomtexturewidth = bloomtextureheight = 0;
6420 // allocate textures as needed
6421 if (r_fb.screentexturewidth != screentexturewidth
6422 || r_fb.screentextureheight != screentextureheight
6423 || r_fb.bloomtexturewidth != bloomtexturewidth
6424 || r_fb.bloomtextureheight != bloomtextureheight
6425 || r_fb.textype != textype
6426 || useviewfbo != (r_fb.fbo != 0))
6428 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6430 if (r_fb.bloomtexture[i])
6431 R_FreeTexture(r_fb.bloomtexture[i]);
6432 r_fb.bloomtexture[i] = NULL;
6434 if (r_fb.bloomfbo[i])
6435 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6436 r_fb.bloomfbo[i] = 0;
6440 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6443 if (r_fb.colortexture)
6444 R_FreeTexture(r_fb.colortexture);
6445 r_fb.colortexture = NULL;
6447 if (r_fb.depthtexture)
6448 R_FreeTexture(r_fb.depthtexture);
6449 r_fb.depthtexture = NULL;
6451 if (r_fb.ghosttexture)
6452 R_FreeTexture(r_fb.ghosttexture);
6453 r_fb.ghosttexture = NULL;
6455 r_fb.screentexturewidth = screentexturewidth;
6456 r_fb.screentextureheight = screentextureheight;
6457 r_fb.bloomtexturewidth = bloomtexturewidth;
6458 r_fb.bloomtextureheight = bloomtextureheight;
6459 r_fb.textype = textype;
6461 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6463 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6464 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6465 r_fb.ghosttexture_valid = false;
6466 r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6469 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6470 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6471 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6475 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6477 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6479 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6481 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6486 // bloom texture is a different resolution
6487 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6488 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6489 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6490 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6491 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6493 // set up a texcoord array for the full resolution screen image
6494 // (we have to keep this around to copy back during final render)
6495 r_fb.screentexcoord2f[0] = 0;
6496 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6497 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6498 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6499 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6500 r_fb.screentexcoord2f[5] = 0;
6501 r_fb.screentexcoord2f[6] = 0;
6502 r_fb.screentexcoord2f[7] = 0;
6506 for (i = 1;i < 8;i += 2)
6508 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6512 // set up a texcoord array for the reduced resolution bloom image
6513 // (which will be additive blended over the screen image)
6514 r_fb.bloomtexcoord2f[0] = 0;
6515 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6516 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6517 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6518 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6519 r_fb.bloomtexcoord2f[5] = 0;
6520 r_fb.bloomtexcoord2f[6] = 0;
6521 r_fb.bloomtexcoord2f[7] = 0;
6523 switch(vid.renderpath)
6525 case RENDERPATH_GL11:
6526 case RENDERPATH_GL13:
6527 case RENDERPATH_GL20:
6528 case RENDERPATH_SOFT:
6529 case RENDERPATH_GLES1:
6530 case RENDERPATH_GLES2:
6532 case RENDERPATH_D3D9:
6533 case RENDERPATH_D3D10:
6534 case RENDERPATH_D3D11:
6535 for (i = 0;i < 4;i++)
6537 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6538 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6539 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6540 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6545 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6548 r_refdef.view.clear = true;
6551 static void R_Bloom_MakeTexture(void)
6554 float xoffset, yoffset, r, brighten;
6556 float colorscale = r_bloom_colorscale.value;
6558 r_refdef.stats[r_stat_bloom]++;
6561 // this copy is unnecessary since it happens in R_BlendView already
6564 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6565 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6569 // scale down screen texture to the bloom texture size
6571 r_fb.bloomindex = 0;
6572 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6573 R_SetViewport(&r_fb.bloomviewport);
6574 GL_DepthTest(false);
6575 GL_BlendFunc(GL_ONE, GL_ZERO);
6576 GL_Color(colorscale, colorscale, colorscale, 1);
6577 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6578 switch(vid.renderpath)
6580 case RENDERPATH_GL11:
6581 case RENDERPATH_GL13:
6582 case RENDERPATH_GL20:
6583 case RENDERPATH_GLES1:
6584 case RENDERPATH_GLES2:
6585 case RENDERPATH_SOFT:
6586 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6588 case RENDERPATH_D3D9:
6589 case RENDERPATH_D3D10:
6590 case RENDERPATH_D3D11:
6591 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6594 // TODO: do boxfilter scale-down in shader?
6595 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6596 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6597 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6599 // we now have a properly scaled bloom image
6600 if (!r_fb.bloomfbo[r_fb.bloomindex])
6602 // copy it into the bloom texture
6603 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6604 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6607 // multiply bloom image by itself as many times as desired
6608 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6610 intex = r_fb.bloomtexture[r_fb.bloomindex];
6611 r_fb.bloomindex ^= 1;
6612 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6614 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6615 if (!r_fb.bloomfbo[r_fb.bloomindex])
6617 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6618 GL_Color(r,r,r,1); // apply fix factor
6623 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6624 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6625 GL_Color(1,1,1,1); // no fix factor supported here
6627 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6628 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6629 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6630 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6632 if (!r_fb.bloomfbo[r_fb.bloomindex])
6634 // copy the darkened image to a texture
6635 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6636 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6640 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6641 brighten = r_bloom_brighten.value;
6642 brighten = sqrt(brighten);
6644 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6646 for (dir = 0;dir < 2;dir++)
6648 intex = r_fb.bloomtexture[r_fb.bloomindex];
6649 r_fb.bloomindex ^= 1;
6650 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6651 // blend on at multiple vertical offsets to achieve a vertical blur
6652 // TODO: do offset blends using GLSL
6653 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6654 GL_BlendFunc(GL_ONE, GL_ZERO);
6655 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6656 for (x = -range;x <= range;x++)
6658 if (!dir){xoffset = 0;yoffset = x;}
6659 else {xoffset = x;yoffset = 0;}
6660 xoffset /= (float)r_fb.bloomtexturewidth;
6661 yoffset /= (float)r_fb.bloomtextureheight;
6662 // compute a texcoord array with the specified x and y offset
6663 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6664 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6665 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6666 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6667 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6668 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6669 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6670 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6671 // this r value looks like a 'dot' particle, fading sharply to
6672 // black at the edges
6673 // (probably not realistic but looks good enough)
6674 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6675 //r = brighten/(range*2+1);
6676 r = brighten / (range * 2 + 1);
6678 r *= (1 - x*x/(float)(range*range));
6679 GL_Color(r, r, r, 1);
6680 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6681 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6682 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6683 GL_BlendFunc(GL_ONE, GL_ONE);
6686 if (!r_fb.bloomfbo[r_fb.bloomindex])
6688 // copy the vertically or horizontally blurred bloom view to a texture
6689 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6690 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6695 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6697 unsigned int permutation;
6698 float uservecs[4][4];
6700 R_EntityMatrix(&identitymatrix);
6702 switch (vid.renderpath)
6704 case RENDERPATH_GL20:
6705 case RENDERPATH_D3D9:
6706 case RENDERPATH_D3D10:
6707 case RENDERPATH_D3D11:
6708 case RENDERPATH_SOFT:
6709 case RENDERPATH_GLES2:
6711 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6712 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6713 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6714 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6715 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6717 if (r_fb.colortexture)
6721 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6722 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6725 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6727 // declare variables
6728 float blur_factor, blur_mouseaccel, blur_velocity;
6729 static float blur_average;
6730 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6732 // set a goal for the factoring
6733 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6734 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6735 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6736 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6737 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6738 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6740 // from the goal, pick an averaged value between goal and last value
6741 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6742 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6744 // enforce minimum amount of blur
6745 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6747 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6749 // calculate values into a standard alpha
6750 cl.motionbluralpha = 1 - exp(-
6752 (r_motionblur.value * blur_factor / 80)
6754 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6757 max(0.0001, cl.time - cl.oldtime) // fps independent
6760 // randomization for the blur value to combat persistent ghosting
6761 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6762 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6765 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6766 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6768 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6769 GL_Color(1, 1, 1, cl.motionbluralpha);
6770 switch(vid.renderpath)
6772 case RENDERPATH_GL11:
6773 case RENDERPATH_GL13:
6774 case RENDERPATH_GL20:
6775 case RENDERPATH_GLES1:
6776 case RENDERPATH_GLES2:
6777 case RENDERPATH_SOFT:
6778 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6780 case RENDERPATH_D3D9:
6781 case RENDERPATH_D3D10:
6782 case RENDERPATH_D3D11:
6783 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6786 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6787 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6788 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6791 // updates old view angles for next pass
6792 VectorCopy(cl.viewangles, blur_oldangles);
6794 // copy view into the ghost texture
6795 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6796 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6797 r_fb.ghosttexture_valid = true;
6802 // no r_fb.colortexture means we're rendering to the real fb
6803 // we may still have to do view tint...
6804 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6806 // apply a color tint to the whole view
6807 R_ResetViewRendering2D(0, NULL, NULL);
6808 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6809 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6810 R_SetupShader_Generic_NoTexture(false, true);
6811 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6812 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6814 break; // no screen processing, no bloom, skip it
6817 if (r_fb.bloomtexture[0])
6819 // make the bloom texture
6820 R_Bloom_MakeTexture();
6823 #if _MSC_VER >= 1400
6824 #define sscanf sscanf_s
6826 memset(uservecs, 0, sizeof(uservecs));
6827 if (r_glsl_postprocess_uservec1_enable.integer)
6828 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6829 if (r_glsl_postprocess_uservec2_enable.integer)
6830 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6831 if (r_glsl_postprocess_uservec3_enable.integer)
6832 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6833 if (r_glsl_postprocess_uservec4_enable.integer)
6834 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6836 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6837 GL_Color(1, 1, 1, 1);
6838 GL_BlendFunc(GL_ONE, GL_ZERO);
6840 switch(vid.renderpath)
6842 case RENDERPATH_GL20:
6843 case RENDERPATH_GLES2:
6844 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6845 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6846 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6847 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6848 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6849 if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6850 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6851 if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6852 if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6853 if (r_glsl_permutation->loc_UserVec3 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6854 if (r_glsl_permutation->loc_UserVec4 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6855 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6856 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6857 if (r_glsl_permutation->loc_BloomColorSubtract >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6859 case RENDERPATH_D3D9:
6861 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6862 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6863 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6864 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6865 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6866 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6867 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6868 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6869 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6870 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6871 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6872 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6873 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6874 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6875 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6878 case RENDERPATH_D3D10:
6879 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6881 case RENDERPATH_D3D11:
6882 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6884 case RENDERPATH_SOFT:
6885 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6886 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6887 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6888 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6889 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6890 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6891 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6892 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6893 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6894 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6895 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6896 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6897 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6898 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6903 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6904 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6906 case RENDERPATH_GL11:
6907 case RENDERPATH_GL13:
6908 case RENDERPATH_GLES1:
6909 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6911 // apply a color tint to the whole view
6912 R_ResetViewRendering2D(0, NULL, NULL);
6913 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6914 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6915 R_SetupShader_Generic_NoTexture(false, true);
6916 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6917 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6923 matrix4x4_t r_waterscrollmatrix;
6925 void R_UpdateFog(void)
6928 if (gamemode == GAME_NEHAHRA)
6930 if (gl_fogenable.integer)
6932 r_refdef.oldgl_fogenable = true;
6933 r_refdef.fog_density = gl_fogdensity.value;
6934 r_refdef.fog_red = gl_fogred.value;
6935 r_refdef.fog_green = gl_foggreen.value;
6936 r_refdef.fog_blue = gl_fogblue.value;
6937 r_refdef.fog_alpha = 1;
6938 r_refdef.fog_start = 0;
6939 r_refdef.fog_end = gl_skyclip.value;
6940 r_refdef.fog_height = 1<<30;
6941 r_refdef.fog_fadedepth = 128;
6943 else if (r_refdef.oldgl_fogenable)
6945 r_refdef.oldgl_fogenable = false;
6946 r_refdef.fog_density = 0;
6947 r_refdef.fog_red = 0;
6948 r_refdef.fog_green = 0;
6949 r_refdef.fog_blue = 0;
6950 r_refdef.fog_alpha = 0;
6951 r_refdef.fog_start = 0;
6952 r_refdef.fog_end = 0;
6953 r_refdef.fog_height = 1<<30;
6954 r_refdef.fog_fadedepth = 128;
6959 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6960 r_refdef.fog_start = max(0, r_refdef.fog_start);
6961 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6963 if (r_refdef.fog_density && r_drawfog.integer)
6965 r_refdef.fogenabled = true;
6966 // this is the point where the fog reaches 0.9986 alpha, which we
6967 // consider a good enough cutoff point for the texture
6968 // (0.9986 * 256 == 255.6)
6969 if (r_fog_exp2.integer)
6970 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6972 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6973 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6974 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6975 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6976 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6977 R_BuildFogHeightTexture();
6978 // fog color was already set
6979 // update the fog texture
6980 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
6981 R_BuildFogTexture();
6982 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6983 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6986 r_refdef.fogenabled = false;
6989 if (r_refdef.fog_density)
6991 r_refdef.fogcolor[0] = r_refdef.fog_red;
6992 r_refdef.fogcolor[1] = r_refdef.fog_green;
6993 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6995 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6996 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6997 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6998 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7002 VectorCopy(r_refdef.fogcolor, fogvec);
7003 // color.rgb *= ContrastBoost * SceneBrightness;
7004 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7005 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7006 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7007 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7012 void R_UpdateVariables(void)
7016 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7018 r_refdef.farclip = r_farclip_base.value;
7019 if (r_refdef.scene.worldmodel)
7020 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7021 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7023 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7024 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7025 r_refdef.polygonfactor = 0;
7026 r_refdef.polygonoffset = 0;
7027 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7028 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7030 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7031 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7032 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7033 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7034 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7035 if (FAKELIGHT_ENABLED)
7037 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7039 else if (r_refdef.scene.worldmodel)
7041 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7043 if (r_showsurfaces.integer)
7045 r_refdef.scene.rtworld = false;
7046 r_refdef.scene.rtworldshadows = false;
7047 r_refdef.scene.rtdlight = false;
7048 r_refdef.scene.rtdlightshadows = false;
7049 r_refdef.lightmapintensity = 0;
7052 r_gpuskeletal = false;
7053 switch(vid.renderpath)
7055 case RENDERPATH_GL20:
7056 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7057 case RENDERPATH_D3D9:
7058 case RENDERPATH_D3D10:
7059 case RENDERPATH_D3D11:
7060 case RENDERPATH_SOFT:
7061 case RENDERPATH_GLES2:
7062 if(v_glslgamma.integer && !vid_gammatables_trivial)
7064 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7066 // build GLSL gamma texture
7067 #define RAMPWIDTH 256
7068 unsigned short ramp[RAMPWIDTH * 3];
7069 unsigned char rampbgr[RAMPWIDTH][4];
7072 r_texture_gammaramps_serial = vid_gammatables_serial;
7074 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7075 for(i = 0; i < RAMPWIDTH; ++i)
7077 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7078 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7079 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7082 if (r_texture_gammaramps)
7084 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7088 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7094 // remove GLSL gamma texture
7097 case RENDERPATH_GL11:
7098 case RENDERPATH_GL13:
7099 case RENDERPATH_GLES1:
7104 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7105 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7111 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7112 if( scenetype != r_currentscenetype ) {
7113 // store the old scenetype
7114 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7115 r_currentscenetype = scenetype;
7116 // move in the new scene
7117 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7126 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7128 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7129 if( scenetype == r_currentscenetype ) {
7130 return &r_refdef.scene;
7132 return &r_scenes_store[ scenetype ];
7136 static int R_SortEntities_Compare(const void *ap, const void *bp)
7138 const entity_render_t *a = *(const entity_render_t **)ap;
7139 const entity_render_t *b = *(const entity_render_t **)bp;
7142 if(a->model < b->model)
7144 if(a->model > b->model)
7148 // TODO possibly calculate the REAL skinnum here first using
7150 if(a->skinnum < b->skinnum)
7152 if(a->skinnum > b->skinnum)
7155 // everything we compared is equal
7158 static void R_SortEntities(void)
7160 // below or equal 2 ents, sorting never gains anything
7161 if(r_refdef.scene.numentities <= 2)
7164 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7172 int dpsoftrast_test;
7173 extern cvar_t r_shadow_bouncegrid;
7174 void R_RenderView(void)
7176 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7178 rtexture_t *depthtexture;
7179 rtexture_t *colortexture;
7181 dpsoftrast_test = r_test.integer;
7183 if (r_timereport_active)
7184 R_TimeReport("start");
7185 r_textureframe++; // used only by R_GetCurrentTexture
7186 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7188 if(R_CompileShader_CheckStaticParms())
7191 if (!r_drawentities.integer)
7192 r_refdef.scene.numentities = 0;
7193 else if (r_sortentities.integer)
7196 R_AnimCache_ClearCache();
7198 /* adjust for stereo display */
7199 if(R_Stereo_Active())
7201 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
7202 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7205 if (r_refdef.view.isoverlay)
7207 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7208 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7209 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7210 R_TimeReport("depthclear");
7212 r_refdef.view.showdebug = false;
7214 r_fb.water.enabled = false;
7215 r_fb.water.numwaterplanes = 0;
7217 R_RenderScene(0, NULL, NULL);
7219 r_refdef.view.matrix = originalmatrix;
7225 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7227 r_refdef.view.matrix = originalmatrix;
7231 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7233 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7234 // in sRGB fallback, behave similar to true sRGB: convert this
7235 // value from linear to sRGB
7236 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7238 R_RenderView_UpdateViewVectors();
7240 R_Shadow_UpdateWorldLightSelection();
7242 R_Bloom_StartFrame();
7244 // apply bloom brightness offset
7245 if(r_fb.bloomtexture[0])
7246 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7248 R_Water_StartFrame();
7250 // now we probably have an fbo to render into
7252 depthtexture = r_fb.depthtexture;
7253 colortexture = r_fb.colortexture;
7256 if (r_timereport_active)
7257 R_TimeReport("viewsetup");
7259 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7261 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7263 R_ClearScreen(r_refdef.fogenabled);
7264 if (r_timereport_active)
7265 R_TimeReport("viewclear");
7267 r_refdef.view.clear = true;
7269 r_refdef.view.showdebug = true;
7272 if (r_timereport_active)
7273 R_TimeReport("visibility");
7275 R_AnimCache_CacheVisibleEntities();
7276 if (r_timereport_active)
7277 R_TimeReport("animcache");
7279 R_Shadow_UpdateBounceGridTexture();
7280 if (r_timereport_active && r_shadow_bouncegrid.integer)
7281 R_TimeReport("bouncegrid");
7283 r_fb.water.numwaterplanes = 0;
7284 if (r_fb.water.enabled)
7285 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7287 R_RenderScene(fbo, depthtexture, colortexture);
7288 r_fb.water.numwaterplanes = 0;
7290 R_BlendView(fbo, depthtexture, colortexture);
7291 if (r_timereport_active)
7292 R_TimeReport("blendview");
7294 GL_Scissor(0, 0, vid.width, vid.height);
7295 GL_ScissorTest(false);
7297 r_refdef.view.matrix = originalmatrix;
7302 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7304 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7306 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7307 if (r_timereport_active)
7308 R_TimeReport("waterworld");
7311 // don't let sound skip if going slow
7312 if (r_refdef.scene.extraupdate)
7315 R_DrawModelsAddWaterPlanes();
7316 if (r_timereport_active)
7317 R_TimeReport("watermodels");
7319 if (r_fb.water.numwaterplanes)
7321 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7322 if (r_timereport_active)
7323 R_TimeReport("waterscenes");
7327 extern cvar_t cl_locs_show;
7328 static void R_DrawLocs(void);
7329 static void R_DrawEntityBBoxes(void);
7330 static void R_DrawModelDecals(void);
7331 extern cvar_t cl_decals_newsystem;
7332 extern qboolean r_shadow_usingdeferredprepass;
7333 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7335 qboolean shadowmapping = false;
7337 if (r_timereport_active)
7338 R_TimeReport("beginscene");
7340 r_refdef.stats[r_stat_renders]++;
7344 // don't let sound skip if going slow
7345 if (r_refdef.scene.extraupdate)
7348 R_MeshQueue_BeginScene();
7352 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
7354 if (r_timereport_active)
7355 R_TimeReport("skystartframe");
7357 if (cl.csqc_vidvars.drawworld)
7359 // don't let sound skip if going slow
7360 if (r_refdef.scene.extraupdate)
7363 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7365 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7366 if (r_timereport_active)
7367 R_TimeReport("worldsky");
7370 if (R_DrawBrushModelsSky() && r_timereport_active)
7371 R_TimeReport("bmodelsky");
7373 if (skyrendermasked && skyrenderlater)
7375 // we have to force off the water clipping plane while rendering sky
7376 R_SetupView(false, fbo, depthtexture, colortexture);
7378 R_SetupView(true, fbo, depthtexture, colortexture);
7379 if (r_timereport_active)
7380 R_TimeReport("sky");
7384 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7385 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7386 R_Shadow_PrepareModelShadows();
7387 if (r_timereport_active)
7388 R_TimeReport("preparelights");
7390 if (R_Shadow_ShadowMappingEnabled())
7391 shadowmapping = true;
7393 if (r_shadow_usingdeferredprepass)
7394 R_Shadow_DrawPrepass();
7396 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7398 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7399 if (r_timereport_active)
7400 R_TimeReport("worlddepth");
7402 if (r_depthfirst.integer >= 2)
7404 R_DrawModelsDepth();
7405 if (r_timereport_active)
7406 R_TimeReport("modeldepth");
7409 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7411 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7412 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7413 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7414 // don't let sound skip if going slow
7415 if (r_refdef.scene.extraupdate)
7419 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7421 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7422 if (r_timereport_active)
7423 R_TimeReport("world");
7426 // don't let sound skip if going slow
7427 if (r_refdef.scene.extraupdate)
7431 if (r_timereport_active)
7432 R_TimeReport("models");
7434 // don't let sound skip if going slow
7435 if (r_refdef.scene.extraupdate)
7438 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7440 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7441 R_DrawModelShadows(fbo, depthtexture, colortexture);
7442 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7443 // don't let sound skip if going slow
7444 if (r_refdef.scene.extraupdate)
7448 if (!r_shadow_usingdeferredprepass)
7450 R_Shadow_DrawLights();
7451 if (r_timereport_active)
7452 R_TimeReport("rtlights");
7455 // don't let sound skip if going slow
7456 if (r_refdef.scene.extraupdate)
7459 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7461 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7462 R_DrawModelShadows(fbo, depthtexture, colortexture);
7463 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7464 // don't let sound skip if going slow
7465 if (r_refdef.scene.extraupdate)
7469 if (cl.csqc_vidvars.drawworld)
7471 if (cl_decals_newsystem.integer)
7473 R_DrawModelDecals();
7474 if (r_timereport_active)
7475 R_TimeReport("modeldecals");
7480 if (r_timereport_active)
7481 R_TimeReport("decals");
7485 if (r_timereport_active)
7486 R_TimeReport("particles");
7489 if (r_timereport_active)
7490 R_TimeReport("explosions");
7492 R_DrawLightningBeams();
7493 if (r_timereport_active)
7494 R_TimeReport("lightning");
7498 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7500 if (r_refdef.view.showdebug)
7502 if (cl_locs_show.integer)
7505 if (r_timereport_active)
7506 R_TimeReport("showlocs");
7509 if (r_drawportals.integer)
7512 if (r_timereport_active)
7513 R_TimeReport("portals");
7516 if (r_showbboxes.value > 0)
7518 R_DrawEntityBBoxes();
7519 if (r_timereport_active)
7520 R_TimeReport("bboxes");
7524 if (r_transparent.integer)
7526 R_MeshQueue_RenderTransparent();
7527 if (r_timereport_active)
7528 R_TimeReport("drawtrans");
7531 if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0 || r_showoverdraw.value > 0))
7533 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7534 if (r_timereport_active)
7535 R_TimeReport("worlddebug");
7536 R_DrawModelsDebug();
7537 if (r_timereport_active)
7538 R_TimeReport("modeldebug");
7541 if (cl.csqc_vidvars.drawworld)
7543 R_Shadow_DrawCoronas();
7544 if (r_timereport_active)
7545 R_TimeReport("coronas");
7550 GL_DepthTest(false);
7551 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7552 GL_Color(1, 1, 1, 1);
7553 qglBegin(GL_POLYGON);
7554 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7555 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7556 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7557 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7559 qglBegin(GL_POLYGON);
7560 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
7561 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
7562 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
7563 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
7565 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7569 // don't let sound skip if going slow
7570 if (r_refdef.scene.extraupdate)
7574 static const unsigned short bboxelements[36] =
7584 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7587 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7589 RSurf_ActiveWorldEntity();
7591 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7592 GL_DepthMask(false);
7593 GL_DepthRange(0, 1);
7594 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7595 // R_Mesh_ResetTextureState();
7597 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7598 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7599 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7600 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7601 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7602 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7603 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7604 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7605 R_FillColors(color4f, 8, cr, cg, cb, ca);
7606 if (r_refdef.fogenabled)
7608 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7610 f1 = RSurf_FogVertex(v);
7612 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7613 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7614 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7617 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7618 R_Mesh_ResetTextureState();
7619 R_SetupShader_Generic_NoTexture(false, false);
7620 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7623 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7625 prvm_prog_t *prog = SVVM_prog;
7628 prvm_edict_t *edict;
7630 // this function draws bounding boxes of server entities
7634 GL_CullFace(GL_NONE);
7635 R_SetupShader_Generic_NoTexture(false, false);
7637 for (i = 0;i < numsurfaces;i++)
7639 edict = PRVM_EDICT_NUM(surfacelist[i]);
7640 switch ((int)PRVM_serveredictfloat(edict, solid))
7642 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7643 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7644 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7645 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7646 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7647 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7648 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7650 color[3] *= r_showbboxes.value;
7651 color[3] = bound(0, color[3], 1);
7652 GL_DepthTest(!r_showdisabledepthtest.integer);
7653 GL_CullFace(r_refdef.view.cullface_front);
7654 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7658 static void R_DrawEntityBBoxes(void)
7661 prvm_edict_t *edict;
7663 prvm_prog_t *prog = SVVM_prog;
7665 // this function draws bounding boxes of server entities
7669 for (i = 0;i < prog->num_edicts;i++)
7671 edict = PRVM_EDICT_NUM(i);
7672 if (edict->priv.server->free)
7674 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7675 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7677 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7679 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7680 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7684 static const int nomodelelement3i[24] =
7696 static const unsigned short nomodelelement3s[24] =
7708 static const float nomodelvertex3f[6*3] =
7718 static const float nomodelcolor4f[6*4] =
7720 0.0f, 0.0f, 0.5f, 1.0f,
7721 0.0f, 0.0f, 0.5f, 1.0f,
7722 0.0f, 0.5f, 0.0f, 1.0f,
7723 0.0f, 0.5f, 0.0f, 1.0f,
7724 0.5f, 0.0f, 0.0f, 1.0f,
7725 0.5f, 0.0f, 0.0f, 1.0f
7728 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7734 RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7736 // this is only called once per entity so numsurfaces is always 1, and
7737 // surfacelist is always {0}, so this code does not handle batches
7739 if (rsurface.ent_flags & RENDER_ADDITIVE)
7741 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7742 GL_DepthMask(false);
7744 else if (rsurface.colormod[3] < 1)
7746 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7747 GL_DepthMask(false);
7751 GL_BlendFunc(GL_ONE, GL_ZERO);
7754 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7755 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7756 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7757 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7758 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7759 for (i = 0, c = color4f;i < 6;i++, c += 4)
7761 c[0] *= rsurface.colormod[0];
7762 c[1] *= rsurface.colormod[1];
7763 c[2] *= rsurface.colormod[2];
7764 c[3] *= rsurface.colormod[3];
7766 if (r_refdef.fogenabled)
7768 for (i = 0, c = color4f;i < 6;i++, c += 4)
7770 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7772 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7773 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7774 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7777 // R_Mesh_ResetTextureState();
7778 R_SetupShader_Generic_NoTexture(false, false);
7779 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7780 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7783 void R_DrawNoModel(entity_render_t *ent)
7786 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7787 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7788 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7790 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7793 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7795 vec3_t right1, right2, diff, normal;
7797 VectorSubtract (org2, org1, normal);
7799 // calculate 'right' vector for start
7800 VectorSubtract (r_refdef.view.origin, org1, diff);
7801 CrossProduct (normal, diff, right1);
7802 VectorNormalize (right1);
7804 // calculate 'right' vector for end
7805 VectorSubtract (r_refdef.view.origin, org2, diff);
7806 CrossProduct (normal, diff, right2);
7807 VectorNormalize (right2);
7809 vert[ 0] = org1[0] + width * right1[0];
7810 vert[ 1] = org1[1] + width * right1[1];
7811 vert[ 2] = org1[2] + width * right1[2];
7812 vert[ 3] = org1[0] - width * right1[0];
7813 vert[ 4] = org1[1] - width * right1[1];
7814 vert[ 5] = org1[2] - width * right1[2];
7815 vert[ 6] = org2[0] - width * right2[0];
7816 vert[ 7] = org2[1] - width * right2[1];
7817 vert[ 8] = org2[2] - width * right2[2];
7818 vert[ 9] = org2[0] + width * right2[0];
7819 vert[10] = org2[1] + width * right2[1];
7820 vert[11] = org2[2] + width * right2[2];
7823 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
7825 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7826 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7827 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7828 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7829 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7830 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7831 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7832 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7833 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7834 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7835 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7836 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7839 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7844 VectorSet(v, x, y, z);
7845 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7846 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7848 if (i == mesh->numvertices)
7850 if (mesh->numvertices < mesh->maxvertices)
7852 VectorCopy(v, vertex3f);
7853 mesh->numvertices++;
7855 return mesh->numvertices;
7861 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7865 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7866 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7867 e = mesh->element3i + mesh->numtriangles * 3;
7868 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7870 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7871 if (mesh->numtriangles < mesh->maxtriangles)
7876 mesh->numtriangles++;
7878 element[1] = element[2];
7882 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7886 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7887 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7888 e = mesh->element3i + mesh->numtriangles * 3;
7889 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7891 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7892 if (mesh->numtriangles < mesh->maxtriangles)
7897 mesh->numtriangles++;
7899 element[1] = element[2];
7903 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7904 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7906 int planenum, planenum2;
7909 mplane_t *plane, *plane2;
7911 double temppoints[2][256*3];
7912 // figure out how large a bounding box we need to properly compute this brush
7914 for (w = 0;w < numplanes;w++)
7915 maxdist = max(maxdist, fabs(planes[w].dist));
7916 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7917 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7918 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7922 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7923 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7925 if (planenum2 == planenum)
7927 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
7930 if (tempnumpoints < 3)
7932 // generate elements forming a triangle fan for this polygon
7933 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7937 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7939 texturelayer_t *layer;
7940 layer = t->currentlayers + t->currentnumlayers++;
7942 layer->depthmask = depthmask;
7943 layer->blendfunc1 = blendfunc1;
7944 layer->blendfunc2 = blendfunc2;
7945 layer->texture = texture;
7946 layer->texmatrix = *matrix;
7947 layer->color[0] = r;
7948 layer->color[1] = g;
7949 layer->color[2] = b;
7950 layer->color[3] = a;
7953 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7955 if(parms[0] == 0 && parms[1] == 0)
7957 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7958 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7963 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7966 index = parms[2] + rsurface.shadertime * parms[3];
7967 index -= floor(index);
7968 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7971 case Q3WAVEFUNC_NONE:
7972 case Q3WAVEFUNC_NOISE:
7973 case Q3WAVEFUNC_COUNT:
7976 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7977 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7978 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7979 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7980 case Q3WAVEFUNC_TRIANGLE:
7982 f = index - floor(index);
7995 f = parms[0] + parms[1] * f;
7996 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7997 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8001 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8008 matrix4x4_t matrix, temp;
8009 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8010 // it's better to have one huge fixup every 9 hours than gradual
8011 // degradation over time which looks consistently bad after many hours.
8013 // tcmod scroll in particular suffers from this degradation which can't be
8014 // effectively worked around even with floor() tricks because we don't
8015 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8016 // a workaround involving floor() would be incorrect anyway...
8017 shadertime = rsurface.shadertime;
8018 if (shadertime >= 32768.0f)
8019 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8020 switch(tcmod->tcmod)
8024 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8025 matrix = r_waterscrollmatrix;
8027 matrix = identitymatrix;
8029 case Q3TCMOD_ENTITYTRANSLATE:
8030 // this is used in Q3 to allow the gamecode to control texcoord
8031 // scrolling on the entity, which is not supported in darkplaces yet.
8032 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8034 case Q3TCMOD_ROTATE:
8035 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8036 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8037 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8040 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8042 case Q3TCMOD_SCROLL:
8043 // this particular tcmod is a "bug for bug" compatible one with regards to
8044 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8045 // specifically did the wrapping and so we must mimic that...
8046 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8047 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8048 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8050 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8051 w = (int) tcmod->parms[0];
8052 h = (int) tcmod->parms[1];
8053 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8055 idx = (int) floor(f * w * h);
8056 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8058 case Q3TCMOD_STRETCH:
8059 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8060 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8062 case Q3TCMOD_TRANSFORM:
8063 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8064 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8065 VectorSet(tcmat + 6, 0 , 0 , 1);
8066 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8067 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8069 case Q3TCMOD_TURBULENT:
8070 // this is handled in the RSurf_PrepareVertices function
8071 matrix = identitymatrix;
8075 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8078 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8080 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8081 char name[MAX_QPATH];
8082 skinframe_t *skinframe;
8083 unsigned char pixels[296*194];
8084 strlcpy(cache->name, skinname, sizeof(cache->name));
8085 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8086 if (developer_loading.integer)
8087 Con_Printf("loading %s\n", name);
8088 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8089 if (!skinframe || !skinframe->base)
8092 fs_offset_t filesize;
8094 f = FS_LoadFile(name, tempmempool, true, &filesize);
8097 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8098 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8102 cache->skinframe = skinframe;
8105 texture_t *R_GetCurrentTexture(texture_t *t)
8108 const entity_render_t *ent = rsurface.entity;
8109 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8110 q3shaderinfo_layer_tcmod_t *tcmod;
8112 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8113 return t->currentframe;
8114 t->update_lastrenderframe = r_textureframe;
8115 t->update_lastrenderentity = (void *)ent;
8117 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8118 t->camera_entity = ent->entitynumber;
8120 t->camera_entity = 0;
8122 // switch to an alternate material if this is a q1bsp animated material
8124 texture_t *texture = t;
8125 int s = rsurface.ent_skinnum;
8126 if ((unsigned int)s >= (unsigned int)model->numskins)
8128 if (model->skinscenes)
8130 if (model->skinscenes[s].framecount > 1)
8131 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8133 s = model->skinscenes[s].firstframe;
8136 t = t + s * model->num_surfaces;
8139 // use an alternate animation if the entity's frame is not 0,
8140 // and only if the texture has an alternate animation
8141 if (rsurface.ent_alttextures && t->anim_total[1])
8142 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8144 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8146 texture->currentframe = t;
8149 // update currentskinframe to be a qw skin or animation frame
8150 if (rsurface.ent_qwskin >= 0)
8152 i = rsurface.ent_qwskin;
8153 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8155 r_qwskincache_size = cl.maxclients;
8157 Mem_Free(r_qwskincache);
8158 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8160 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8161 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8162 t->currentskinframe = r_qwskincache[i].skinframe;
8163 if (t->currentskinframe == NULL)
8164 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8166 else if (t->numskinframes >= 2)
8167 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8168 if (t->backgroundnumskinframes >= 2)
8169 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8171 t->currentmaterialflags = t->basematerialflags;
8172 t->currentalpha = rsurface.colormod[3];
8173 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8174 t->currentalpha *= r_wateralpha.value;
8175 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8176 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8177 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8178 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8179 if (!(rsurface.ent_flags & RENDER_LIGHT))
8180 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8181 else if (FAKELIGHT_ENABLED)
8183 // no modellight if using fakelight for the map
8185 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8187 // pick a model lighting mode
8188 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8189 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8191 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8193 if (rsurface.ent_flags & RENDER_ADDITIVE)
8194 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8195 else if (t->currentalpha < 1)
8196 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8197 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8198 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8199 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8200 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8201 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8202 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8203 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8204 if (t->backgroundnumskinframes)
8205 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8206 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8208 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8209 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8212 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8213 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8215 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8216 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8218 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8219 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8221 // there is no tcmod
8222 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8224 t->currenttexmatrix = r_waterscrollmatrix;
8225 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8227 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8229 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8230 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8233 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8234 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8235 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8236 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8238 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8239 if (t->currentskinframe->qpixels)
8240 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8241 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8242 if (!t->basetexture)
8243 t->basetexture = r_texture_notexture;
8244 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8245 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8246 t->nmaptexture = t->currentskinframe->nmap;
8247 if (!t->nmaptexture)
8248 t->nmaptexture = r_texture_blanknormalmap;
8249 t->glosstexture = r_texture_black;
8250 t->glowtexture = t->currentskinframe->glow;
8251 t->fogtexture = t->currentskinframe->fog;
8252 t->reflectmasktexture = t->currentskinframe->reflect;
8253 if (t->backgroundnumskinframes)
8255 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8256 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8257 t->backgroundglosstexture = r_texture_black;
8258 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8259 if (!t->backgroundnmaptexture)
8260 t->backgroundnmaptexture = r_texture_blanknormalmap;
8261 // make sure that if glow is going to be used, both textures are not NULL
8262 if (!t->backgroundglowtexture && t->glowtexture)
8263 t->backgroundglowtexture = r_texture_black;
8264 if (!t->glowtexture && t->backgroundglowtexture)
8265 t->glowtexture = r_texture_black;
8269 t->backgroundbasetexture = r_texture_white;
8270 t->backgroundnmaptexture = r_texture_blanknormalmap;
8271 t->backgroundglosstexture = r_texture_black;
8272 t->backgroundglowtexture = NULL;
8274 t->specularpower = r_shadow_glossexponent.value;
8275 // TODO: store reference values for these in the texture?
8276 t->specularscale = 0;
8277 if (r_shadow_gloss.integer > 0)
8279 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8281 if (r_shadow_glossintensity.value > 0)
8283 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8284 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8285 t->specularscale = r_shadow_glossintensity.value;
8288 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8290 t->glosstexture = r_texture_white;
8291 t->backgroundglosstexture = r_texture_white;
8292 t->specularscale = r_shadow_gloss2intensity.value;
8293 t->specularpower = r_shadow_gloss2exponent.value;
8296 t->specularscale *= t->specularscalemod;
8297 t->specularpower *= t->specularpowermod;
8298 t->rtlightambient = 0;
8300 // lightmaps mode looks bad with dlights using actual texturing, so turn
8301 // off the colormap and glossmap, but leave the normalmap on as it still
8302 // accurately represents the shading involved
8303 if (gl_lightmaps.integer)
8305 t->basetexture = r_texture_grey128;
8306 t->pantstexture = r_texture_black;
8307 t->shirttexture = r_texture_black;
8308 if (gl_lightmaps.integer < 2)
8309 t->nmaptexture = r_texture_blanknormalmap;
8310 t->glosstexture = r_texture_black;
8311 t->glowtexture = NULL;
8312 t->fogtexture = NULL;
8313 t->reflectmasktexture = NULL;
8314 t->backgroundbasetexture = NULL;
8315 if (gl_lightmaps.integer < 2)
8316 t->backgroundnmaptexture = r_texture_blanknormalmap;
8317 t->backgroundglosstexture = r_texture_black;
8318 t->backgroundglowtexture = NULL;
8319 t->specularscale = 0;
8320 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8323 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8324 VectorClear(t->dlightcolor);
8325 t->currentnumlayers = 0;
8326 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8328 int blendfunc1, blendfunc2;
8330 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8332 blendfunc1 = GL_SRC_ALPHA;
8333 blendfunc2 = GL_ONE;
8335 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8337 blendfunc1 = GL_SRC_ALPHA;
8338 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8340 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8342 blendfunc1 = t->customblendfunc[0];
8343 blendfunc2 = t->customblendfunc[1];
8347 blendfunc1 = GL_ONE;
8348 blendfunc2 = GL_ZERO;
8350 // don't colormod evilblend textures
8351 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8352 VectorSet(t->lightmapcolor, 1, 1, 1);
8353 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8354 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8356 // fullbright is not affected by r_refdef.lightmapintensity
8357 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]);
8358 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8359 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]);
8360 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8361 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]);
8365 vec3_t ambientcolor;
8367 // set the color tint used for lights affecting this surface
8368 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8370 // q3bsp has no lightmap updates, so the lightstylevalue that
8371 // would normally be baked into the lightmap must be
8372 // applied to the color
8373 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8374 if (model->type == mod_brushq3)
8375 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8376 colorscale *= r_refdef.lightmapintensity;
8377 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8378 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8379 // basic lit geometry
8380 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]);
8381 // add pants/shirt if needed
8382 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8383 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]);
8384 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8385 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]);
8386 // now add ambient passes if needed
8387 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8389 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]);
8390 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8391 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]);
8392 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8393 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]);
8396 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8397 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]);
8398 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8400 // if this is opaque use alpha blend which will darken the earlier
8403 // if this is an alpha blended material, all the earlier passes
8404 // were darkened by fog already, so we only need to add the fog
8405 // color ontop through the fog mask texture
8407 // if this is an additive blended material, all the earlier passes
8408 // were darkened by fog already, and we should not add fog color
8409 // (because the background was not darkened, there is no fog color
8410 // that was lost behind it).
8411 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]);
8415 return t->currentframe;
8418 rsurfacestate_t rsurface;
8420 void RSurf_ActiveWorldEntity(void)
8422 dp_model_t *model = r_refdef.scene.worldmodel;
8423 //if (rsurface.entity == r_refdef.scene.worldentity)
8425 rsurface.entity = r_refdef.scene.worldentity;
8426 rsurface.skeleton = NULL;
8427 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8428 rsurface.ent_skinnum = 0;
8429 rsurface.ent_qwskin = -1;
8430 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8431 rsurface.shadertime = r_refdef.scene.time;
8432 rsurface.matrix = identitymatrix;
8433 rsurface.inversematrix = identitymatrix;
8434 rsurface.matrixscale = 1;
8435 rsurface.inversematrixscale = 1;
8436 R_EntityMatrix(&identitymatrix);
8437 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8438 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8439 rsurface.fograngerecip = r_refdef.fograngerecip;
8440 rsurface.fogheightfade = r_refdef.fogheightfade;
8441 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8442 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8443 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8444 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8445 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8446 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8447 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8448 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8449 rsurface.colormod[3] = 1;
8450 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);
8451 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8452 rsurface.frameblend[0].lerp = 1;
8453 rsurface.ent_alttextures = false;
8454 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8455 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8456 rsurface.entityskeletaltransform3x4 = NULL;
8457 rsurface.entityskeletaltransform3x4buffer = NULL;
8458 rsurface.entityskeletaltransform3x4offset = 0;
8459 rsurface.entityskeletaltransform3x4size = 0;;
8460 rsurface.entityskeletalnumtransforms = 0;
8461 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8462 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8463 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8464 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8465 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8466 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8467 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8468 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8469 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8470 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8471 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8472 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8473 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8474 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8475 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8476 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8477 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8478 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8479 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8480 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8481 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8482 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8483 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8484 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8485 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8486 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8487 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8488 rsurface.modelelement3i = model->surfmesh.data_element3i;
8489 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8490 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8491 rsurface.modelelement3s = model->surfmesh.data_element3s;
8492 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8493 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8494 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8495 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8496 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8497 rsurface.modelsurfaces = model->data_surfaces;
8498 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8499 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8500 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8501 rsurface.modelgeneratedvertex = false;
8502 rsurface.batchgeneratedvertex = false;
8503 rsurface.batchfirstvertex = 0;
8504 rsurface.batchnumvertices = 0;
8505 rsurface.batchfirsttriangle = 0;
8506 rsurface.batchnumtriangles = 0;
8507 rsurface.batchvertex3f = NULL;
8508 rsurface.batchvertex3f_vertexbuffer = NULL;
8509 rsurface.batchvertex3f_bufferoffset = 0;
8510 rsurface.batchsvector3f = NULL;
8511 rsurface.batchsvector3f_vertexbuffer = NULL;
8512 rsurface.batchsvector3f_bufferoffset = 0;
8513 rsurface.batchtvector3f = NULL;
8514 rsurface.batchtvector3f_vertexbuffer = NULL;
8515 rsurface.batchtvector3f_bufferoffset = 0;
8516 rsurface.batchnormal3f = NULL;
8517 rsurface.batchnormal3f_vertexbuffer = NULL;
8518 rsurface.batchnormal3f_bufferoffset = 0;
8519 rsurface.batchlightmapcolor4f = NULL;
8520 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8521 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8522 rsurface.batchtexcoordtexture2f = NULL;
8523 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8524 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8525 rsurface.batchtexcoordlightmap2f = NULL;
8526 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8527 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8528 rsurface.batchskeletalindex4ub = NULL;
8529 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8530 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8531 rsurface.batchskeletalweight4ub = NULL;
8532 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8533 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8534 rsurface.batchvertexmesh = NULL;
8535 rsurface.batchvertexmesh_vertexbuffer = NULL;
8536 rsurface.batchvertexmesh_bufferoffset = 0;
8537 rsurface.batchelement3i = NULL;
8538 rsurface.batchelement3i_indexbuffer = NULL;
8539 rsurface.batchelement3i_bufferoffset = 0;
8540 rsurface.batchelement3s = NULL;
8541 rsurface.batchelement3s_indexbuffer = NULL;
8542 rsurface.batchelement3s_bufferoffset = 0;
8543 rsurface.passcolor4f = NULL;
8544 rsurface.passcolor4f_vertexbuffer = NULL;
8545 rsurface.passcolor4f_bufferoffset = 0;
8546 rsurface.forcecurrenttextureupdate = false;
8549 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8551 dp_model_t *model = ent->model;
8552 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8554 rsurface.entity = (entity_render_t *)ent;
8555 rsurface.skeleton = ent->skeleton;
8556 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8557 rsurface.ent_skinnum = ent->skinnum;
8558 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;
8559 rsurface.ent_flags = ent->flags;
8560 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8561 rsurface.matrix = ent->matrix;
8562 rsurface.inversematrix = ent->inversematrix;
8563 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8564 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8565 R_EntityMatrix(&rsurface.matrix);
8566 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8567 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8568 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8569 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8570 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8571 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8572 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8573 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8574 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8575 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8576 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8577 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8578 rsurface.colormod[3] = ent->alpha;
8579 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8580 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8581 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8582 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8583 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8584 if (ent->model->brush.submodel && !prepass)
8586 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8587 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8589 // if the animcache code decided it should use the shader path, skip the deform step
8590 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8591 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8592 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8593 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8594 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8595 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8597 if (ent->animcache_vertex3f)
8599 r_refdef.stats[r_stat_batch_entitycache_count]++;
8600 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8601 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8602 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8603 rsurface.modelvertex3f = ent->animcache_vertex3f;
8604 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8605 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8606 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8607 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8608 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8609 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8610 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8611 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8612 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8613 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8614 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8615 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8616 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8617 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8619 else if (wanttangents)
8621 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8622 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8623 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8624 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8625 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8626 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8627 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8628 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8629 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8630 rsurface.modelvertexmesh = NULL;
8631 rsurface.modelvertexmesh_vertexbuffer = NULL;
8632 rsurface.modelvertexmesh_bufferoffset = 0;
8633 rsurface.modelvertex3f_vertexbuffer = NULL;
8634 rsurface.modelvertex3f_bufferoffset = 0;
8635 rsurface.modelvertex3f_vertexbuffer = 0;
8636 rsurface.modelvertex3f_bufferoffset = 0;
8637 rsurface.modelsvector3f_vertexbuffer = 0;
8638 rsurface.modelsvector3f_bufferoffset = 0;
8639 rsurface.modeltvector3f_vertexbuffer = 0;
8640 rsurface.modeltvector3f_bufferoffset = 0;
8641 rsurface.modelnormal3f_vertexbuffer = 0;
8642 rsurface.modelnormal3f_bufferoffset = 0;
8644 else if (wantnormals)
8646 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8647 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8648 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8649 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8650 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8651 rsurface.modelsvector3f = NULL;
8652 rsurface.modeltvector3f = NULL;
8653 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8654 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8655 rsurface.modelvertexmesh = NULL;
8656 rsurface.modelvertexmesh_vertexbuffer = NULL;
8657 rsurface.modelvertexmesh_bufferoffset = 0;
8658 rsurface.modelvertex3f_vertexbuffer = NULL;
8659 rsurface.modelvertex3f_bufferoffset = 0;
8660 rsurface.modelvertex3f_vertexbuffer = 0;
8661 rsurface.modelvertex3f_bufferoffset = 0;
8662 rsurface.modelsvector3f_vertexbuffer = 0;
8663 rsurface.modelsvector3f_bufferoffset = 0;
8664 rsurface.modeltvector3f_vertexbuffer = 0;
8665 rsurface.modeltvector3f_bufferoffset = 0;
8666 rsurface.modelnormal3f_vertexbuffer = 0;
8667 rsurface.modelnormal3f_bufferoffset = 0;
8671 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8672 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8673 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8674 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8675 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8676 rsurface.modelsvector3f = NULL;
8677 rsurface.modeltvector3f = NULL;
8678 rsurface.modelnormal3f = NULL;
8679 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8680 rsurface.modelvertexmesh = NULL;
8681 rsurface.modelvertexmesh_vertexbuffer = NULL;
8682 rsurface.modelvertexmesh_bufferoffset = 0;
8683 rsurface.modelvertex3f_vertexbuffer = NULL;
8684 rsurface.modelvertex3f_bufferoffset = 0;
8685 rsurface.modelvertex3f_vertexbuffer = 0;
8686 rsurface.modelvertex3f_bufferoffset = 0;
8687 rsurface.modelsvector3f_vertexbuffer = 0;
8688 rsurface.modelsvector3f_bufferoffset = 0;
8689 rsurface.modeltvector3f_vertexbuffer = 0;
8690 rsurface.modeltvector3f_bufferoffset = 0;
8691 rsurface.modelnormal3f_vertexbuffer = 0;
8692 rsurface.modelnormal3f_bufferoffset = 0;
8694 rsurface.modelgeneratedvertex = true;
8698 if (rsurface.entityskeletaltransform3x4)
8700 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8701 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8702 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8703 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8707 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8708 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8709 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8710 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8712 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8713 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8714 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8715 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8716 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8717 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8718 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8719 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8720 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8721 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8722 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8723 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8724 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8725 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8726 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8727 rsurface.modelgeneratedvertex = false;
8729 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8730 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8731 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8732 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8733 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8734 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8735 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8736 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8737 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8738 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8739 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8740 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8741 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8742 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8743 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8744 rsurface.modelelement3i = model->surfmesh.data_element3i;
8745 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8746 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8747 rsurface.modelelement3s = model->surfmesh.data_element3s;
8748 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8749 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8750 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8751 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8752 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8753 rsurface.modelsurfaces = model->data_surfaces;
8754 rsurface.batchgeneratedvertex = false;
8755 rsurface.batchfirstvertex = 0;
8756 rsurface.batchnumvertices = 0;
8757 rsurface.batchfirsttriangle = 0;
8758 rsurface.batchnumtriangles = 0;
8759 rsurface.batchvertex3f = NULL;
8760 rsurface.batchvertex3f_vertexbuffer = NULL;
8761 rsurface.batchvertex3f_bufferoffset = 0;
8762 rsurface.batchsvector3f = NULL;
8763 rsurface.batchsvector3f_vertexbuffer = NULL;
8764 rsurface.batchsvector3f_bufferoffset = 0;
8765 rsurface.batchtvector3f = NULL;
8766 rsurface.batchtvector3f_vertexbuffer = NULL;
8767 rsurface.batchtvector3f_bufferoffset = 0;
8768 rsurface.batchnormal3f = NULL;
8769 rsurface.batchnormal3f_vertexbuffer = NULL;
8770 rsurface.batchnormal3f_bufferoffset = 0;
8771 rsurface.batchlightmapcolor4f = NULL;
8772 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8773 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8774 rsurface.batchtexcoordtexture2f = NULL;
8775 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8776 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8777 rsurface.batchtexcoordlightmap2f = NULL;
8778 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8779 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8780 rsurface.batchskeletalindex4ub = NULL;
8781 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8782 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8783 rsurface.batchskeletalweight4ub = NULL;
8784 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8785 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8786 rsurface.batchvertexmesh = NULL;
8787 rsurface.batchvertexmesh_vertexbuffer = NULL;
8788 rsurface.batchvertexmesh_bufferoffset = 0;
8789 rsurface.batchelement3i = NULL;
8790 rsurface.batchelement3i_indexbuffer = NULL;
8791 rsurface.batchelement3i_bufferoffset = 0;
8792 rsurface.batchelement3s = NULL;
8793 rsurface.batchelement3s_indexbuffer = NULL;
8794 rsurface.batchelement3s_bufferoffset = 0;
8795 rsurface.passcolor4f = NULL;
8796 rsurface.passcolor4f_vertexbuffer = NULL;
8797 rsurface.passcolor4f_bufferoffset = 0;
8798 rsurface.forcecurrenttextureupdate = false;
8801 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)
8803 rsurface.entity = r_refdef.scene.worldentity;
8804 rsurface.skeleton = NULL;
8805 rsurface.ent_skinnum = 0;
8806 rsurface.ent_qwskin = -1;
8807 rsurface.ent_flags = entflags;
8808 rsurface.shadertime = r_refdef.scene.time - shadertime;
8809 rsurface.modelnumvertices = numvertices;
8810 rsurface.modelnumtriangles = numtriangles;
8811 rsurface.matrix = *matrix;
8812 rsurface.inversematrix = *inversematrix;
8813 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8814 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8815 R_EntityMatrix(&rsurface.matrix);
8816 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8817 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8818 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8819 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8820 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8821 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8822 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8823 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8824 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8825 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8826 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8827 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8828 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);
8829 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8830 rsurface.frameblend[0].lerp = 1;
8831 rsurface.ent_alttextures = false;
8832 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8833 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8834 rsurface.entityskeletaltransform3x4 = NULL;
8835 rsurface.entityskeletaltransform3x4buffer = NULL;
8836 rsurface.entityskeletaltransform3x4offset = 0;
8837 rsurface.entityskeletaltransform3x4size = 0;
8838 rsurface.entityskeletalnumtransforms = 0;
8839 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8840 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8841 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8842 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8845 rsurface.modelvertex3f = (float *)vertex3f;
8846 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8847 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8848 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8850 else if (wantnormals)
8852 rsurface.modelvertex3f = (float *)vertex3f;
8853 rsurface.modelsvector3f = NULL;
8854 rsurface.modeltvector3f = NULL;
8855 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8859 rsurface.modelvertex3f = (float *)vertex3f;
8860 rsurface.modelsvector3f = NULL;
8861 rsurface.modeltvector3f = NULL;
8862 rsurface.modelnormal3f = NULL;
8864 rsurface.modelvertexmesh = NULL;
8865 rsurface.modelvertexmesh_vertexbuffer = NULL;
8866 rsurface.modelvertexmesh_bufferoffset = 0;
8867 rsurface.modelvertex3f_vertexbuffer = 0;
8868 rsurface.modelvertex3f_bufferoffset = 0;
8869 rsurface.modelsvector3f_vertexbuffer = 0;
8870 rsurface.modelsvector3f_bufferoffset = 0;
8871 rsurface.modeltvector3f_vertexbuffer = 0;
8872 rsurface.modeltvector3f_bufferoffset = 0;
8873 rsurface.modelnormal3f_vertexbuffer = 0;
8874 rsurface.modelnormal3f_bufferoffset = 0;
8875 rsurface.modelgeneratedvertex = true;
8876 rsurface.modellightmapcolor4f = (float *)color4f;
8877 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8878 rsurface.modellightmapcolor4f_bufferoffset = 0;
8879 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8880 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8881 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8882 rsurface.modeltexcoordlightmap2f = NULL;
8883 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8884 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8885 rsurface.modelskeletalindex4ub = NULL;
8886 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8887 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8888 rsurface.modelskeletalweight4ub = NULL;
8889 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8890 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8891 rsurface.modelelement3i = (int *)element3i;
8892 rsurface.modelelement3i_indexbuffer = NULL;
8893 rsurface.modelelement3i_bufferoffset = 0;
8894 rsurface.modelelement3s = (unsigned short *)element3s;
8895 rsurface.modelelement3s_indexbuffer = NULL;
8896 rsurface.modelelement3s_bufferoffset = 0;
8897 rsurface.modellightmapoffsets = NULL;
8898 rsurface.modelsurfaces = NULL;
8899 rsurface.batchgeneratedvertex = false;
8900 rsurface.batchfirstvertex = 0;
8901 rsurface.batchnumvertices = 0;
8902 rsurface.batchfirsttriangle = 0;
8903 rsurface.batchnumtriangles = 0;
8904 rsurface.batchvertex3f = NULL;
8905 rsurface.batchvertex3f_vertexbuffer = NULL;
8906 rsurface.batchvertex3f_bufferoffset = 0;
8907 rsurface.batchsvector3f = NULL;
8908 rsurface.batchsvector3f_vertexbuffer = NULL;
8909 rsurface.batchsvector3f_bufferoffset = 0;
8910 rsurface.batchtvector3f = NULL;
8911 rsurface.batchtvector3f_vertexbuffer = NULL;
8912 rsurface.batchtvector3f_bufferoffset = 0;
8913 rsurface.batchnormal3f = NULL;
8914 rsurface.batchnormal3f_vertexbuffer = NULL;
8915 rsurface.batchnormal3f_bufferoffset = 0;
8916 rsurface.batchlightmapcolor4f = NULL;
8917 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8918 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8919 rsurface.batchtexcoordtexture2f = NULL;
8920 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8921 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8922 rsurface.batchtexcoordlightmap2f = NULL;
8923 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8924 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8925 rsurface.batchskeletalindex4ub = NULL;
8926 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8927 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8928 rsurface.batchskeletalweight4ub = NULL;
8929 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8930 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8931 rsurface.batchvertexmesh = NULL;
8932 rsurface.batchvertexmesh_vertexbuffer = NULL;
8933 rsurface.batchvertexmesh_bufferoffset = 0;
8934 rsurface.batchelement3i = NULL;
8935 rsurface.batchelement3i_indexbuffer = NULL;
8936 rsurface.batchelement3i_bufferoffset = 0;
8937 rsurface.batchelement3s = NULL;
8938 rsurface.batchelement3s_indexbuffer = NULL;
8939 rsurface.batchelement3s_bufferoffset = 0;
8940 rsurface.passcolor4f = NULL;
8941 rsurface.passcolor4f_vertexbuffer = NULL;
8942 rsurface.passcolor4f_bufferoffset = 0;
8943 rsurface.forcecurrenttextureupdate = true;
8945 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8947 if ((wantnormals || wanttangents) && !normal3f)
8949 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8950 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8952 if (wanttangents && !svector3f)
8954 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8955 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8956 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8961 float RSurf_FogPoint(const float *v)
8963 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8964 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8965 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8966 float FogHeightFade = r_refdef.fogheightfade;
8968 unsigned int fogmasktableindex;
8969 if (r_refdef.fogplaneviewabove)
8970 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8972 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8973 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8974 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8977 float RSurf_FogVertex(const float *v)
8979 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8980 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8981 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8982 float FogHeightFade = rsurface.fogheightfade;
8984 unsigned int fogmasktableindex;
8985 if (r_refdef.fogplaneviewabove)
8986 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8988 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8989 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8990 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8993 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8996 for (i = 0;i < numelements;i++)
8997 outelement3i[i] = inelement3i[i] + adjust;
9000 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9001 extern cvar_t gl_vbo;
9002 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9010 int surfacefirsttriangle;
9011 int surfacenumtriangles;
9012 int surfacefirstvertex;
9013 int surfaceendvertex;
9014 int surfacenumvertices;
9015 int batchnumsurfaces = texturenumsurfaces;
9016 int batchnumvertices;
9017 int batchnumtriangles;
9021 qboolean dynamicvertex;
9025 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9028 q3shaderinfo_deform_t *deform;
9029 const msurface_t *surface, *firstsurface;
9030 r_vertexmesh_t *vertexmesh;
9031 if (!texturenumsurfaces)
9033 // find vertex range of this surface batch
9035 firstsurface = texturesurfacelist[0];
9036 firsttriangle = firstsurface->num_firsttriangle;
9037 batchnumvertices = 0;
9038 batchnumtriangles = 0;
9039 firstvertex = endvertex = firstsurface->num_firstvertex;
9040 for (i = 0;i < texturenumsurfaces;i++)
9042 surface = texturesurfacelist[i];
9043 if (surface != firstsurface + i)
9045 surfacefirstvertex = surface->num_firstvertex;
9046 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9047 surfacenumvertices = surface->num_vertices;
9048 surfacenumtriangles = surface->num_triangles;
9049 if (firstvertex > surfacefirstvertex)
9050 firstvertex = surfacefirstvertex;
9051 if (endvertex < surfaceendvertex)
9052 endvertex = surfaceendvertex;
9053 batchnumvertices += surfacenumvertices;
9054 batchnumtriangles += surfacenumtriangles;
9057 r_refdef.stats[r_stat_batch_batches]++;
9059 r_refdef.stats[r_stat_batch_withgaps]++;
9060 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9061 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9062 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9064 // we now know the vertex range used, and if there are any gaps in it
9065 rsurface.batchfirstvertex = firstvertex;
9066 rsurface.batchnumvertices = endvertex - firstvertex;
9067 rsurface.batchfirsttriangle = firsttriangle;
9068 rsurface.batchnumtriangles = batchnumtriangles;
9070 // this variable holds flags for which properties have been updated that
9071 // may require regenerating vertexmesh array...
9074 // check if any dynamic vertex processing must occur
9075 dynamicvertex = false;
9077 // a cvar to force the dynamic vertex path to be taken, for debugging
9078 if (r_batch_debugdynamicvertexpath.integer)
9082 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9083 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9084 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9085 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9087 dynamicvertex = true;
9090 // if there is a chance of animated vertex colors, it's a dynamic batch
9091 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9095 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9096 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9097 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9098 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9100 dynamicvertex = true;
9101 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9104 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9106 switch (deform->deform)
9109 case Q3DEFORM_PROJECTIONSHADOW:
9110 case Q3DEFORM_TEXT0:
9111 case Q3DEFORM_TEXT1:
9112 case Q3DEFORM_TEXT2:
9113 case Q3DEFORM_TEXT3:
9114 case Q3DEFORM_TEXT4:
9115 case Q3DEFORM_TEXT5:
9116 case Q3DEFORM_TEXT6:
9117 case Q3DEFORM_TEXT7:
9120 case Q3DEFORM_AUTOSPRITE:
9123 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9124 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9125 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9126 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9128 dynamicvertex = true;
9129 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9130 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9132 case Q3DEFORM_AUTOSPRITE2:
9135 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9136 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9137 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9138 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9140 dynamicvertex = true;
9141 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9142 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9144 case Q3DEFORM_NORMAL:
9147 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9148 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9149 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9150 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9152 dynamicvertex = true;
9153 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9154 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9157 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9158 break; // if wavefunc is a nop, ignore this transform
9161 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9162 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9163 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9164 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9166 dynamicvertex = true;
9167 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9168 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9170 case Q3DEFORM_BULGE:
9173 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9174 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9175 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9176 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9178 dynamicvertex = true;
9179 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9180 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9183 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9184 break; // if wavefunc is a nop, ignore this transform
9187 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9188 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9189 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9190 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9192 dynamicvertex = true;
9193 batchneed |= BATCHNEED_ARRAY_VERTEX;
9194 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9198 switch(rsurface.texture->tcgen.tcgen)
9201 case Q3TCGEN_TEXTURE:
9203 case Q3TCGEN_LIGHTMAP:
9206 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9207 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9208 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9209 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9211 dynamicvertex = true;
9212 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9213 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9215 case Q3TCGEN_VECTOR:
9218 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9219 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9220 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9221 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9223 dynamicvertex = true;
9224 batchneed |= BATCHNEED_ARRAY_VERTEX;
9225 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9227 case Q3TCGEN_ENVIRONMENT:
9230 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9231 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9232 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9233 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9235 dynamicvertex = true;
9236 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9237 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9240 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9244 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9245 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9246 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9247 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9249 dynamicvertex = true;
9250 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9251 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9254 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9258 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9259 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9260 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9261 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9263 dynamicvertex = true;
9264 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9267 // when the model data has no vertex buffer (dynamic mesh), we need to
9269 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9270 batchneed |= BATCHNEED_NOGAPS;
9272 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9273 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9274 // we ensure this by treating the vertex batch as dynamic...
9275 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9279 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9280 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9281 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9282 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9284 dynamicvertex = true;
9289 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9290 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9291 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9292 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9293 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9294 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9295 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9296 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9299 // if needsupdate, we have to do a dynamic vertex batch for sure
9300 if (needsupdate & batchneed)
9304 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9305 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9306 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9307 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9309 dynamicvertex = true;
9312 // see if we need to build vertexmesh from arrays
9313 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9317 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9318 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9319 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9320 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9322 dynamicvertex = true;
9325 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9326 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9327 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9329 rsurface.batchvertex3f = rsurface.modelvertex3f;
9330 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9331 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9332 rsurface.batchsvector3f = rsurface.modelsvector3f;
9333 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9334 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9335 rsurface.batchtvector3f = rsurface.modeltvector3f;
9336 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9337 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9338 rsurface.batchnormal3f = rsurface.modelnormal3f;
9339 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9340 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9341 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9342 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9343 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9344 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9345 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9346 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9347 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9348 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9349 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9350 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9351 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9352 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9353 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9354 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9355 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9356 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9357 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9358 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9359 rsurface.batchelement3i = rsurface.modelelement3i;
9360 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9361 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9362 rsurface.batchelement3s = rsurface.modelelement3s;
9363 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9364 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9365 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9366 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9367 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9368 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9369 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9371 // if any dynamic vertex processing has to occur in software, we copy the
9372 // entire surface list together before processing to rebase the vertices
9373 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9375 // if any gaps exist and we do not have a static vertex buffer, we have to
9376 // copy the surface list together to avoid wasting upload bandwidth on the
9377 // vertices in the gaps.
9379 // if gaps exist and we have a static vertex buffer, we can choose whether
9380 // to combine the index buffer ranges into one dynamic index buffer or
9381 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9383 // in many cases the batch is reduced to one draw call.
9385 rsurface.batchmultidraw = false;
9386 rsurface.batchmultidrawnumsurfaces = 0;
9387 rsurface.batchmultidrawsurfacelist = NULL;
9391 // static vertex data, just set pointers...
9392 rsurface.batchgeneratedvertex = false;
9393 // if there are gaps, we want to build a combined index buffer,
9394 // otherwise use the original static buffer with an appropriate offset
9397 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9398 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9399 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9400 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9401 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9403 rsurface.batchmultidraw = true;
9404 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9405 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9408 // build a new triangle elements array for this batch
9409 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9410 rsurface.batchfirsttriangle = 0;
9412 for (i = 0;i < texturenumsurfaces;i++)
9414 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9415 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9416 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9417 numtriangles += surfacenumtriangles;
9419 rsurface.batchelement3i_indexbuffer = NULL;
9420 rsurface.batchelement3i_bufferoffset = 0;
9421 rsurface.batchelement3s = NULL;
9422 rsurface.batchelement3s_indexbuffer = NULL;
9423 rsurface.batchelement3s_bufferoffset = 0;
9424 if (endvertex <= 65536)
9426 // make a 16bit (unsigned short) index array if possible
9427 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9428 for (i = 0;i < numtriangles*3;i++)
9429 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9431 // upload buffer data for the copytriangles batch
9432 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9434 if (rsurface.batchelement3s)
9435 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9436 else if (rsurface.batchelement3i)
9437 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9442 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9443 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9444 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9445 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9450 // something needs software processing, do it for real...
9451 // we only directly handle separate array data in this case and then
9452 // generate interleaved data if needed...
9453 rsurface.batchgeneratedvertex = true;
9454 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9455 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9456 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9457 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9459 // now copy the vertex data into a combined array and make an index array
9460 // (this is what Quake3 does all the time)
9461 // we also apply any skeletal animation here that would have been done in
9462 // the vertex shader, because most of the dynamic vertex animation cases
9463 // need actual vertex positions and normals
9464 //if (dynamicvertex)
9466 rsurface.batchvertexmesh = NULL;
9467 rsurface.batchvertexmesh_vertexbuffer = NULL;
9468 rsurface.batchvertexmesh_bufferoffset = 0;
9469 rsurface.batchvertex3f = NULL;
9470 rsurface.batchvertex3f_vertexbuffer = NULL;
9471 rsurface.batchvertex3f_bufferoffset = 0;
9472 rsurface.batchsvector3f = NULL;
9473 rsurface.batchsvector3f_vertexbuffer = NULL;
9474 rsurface.batchsvector3f_bufferoffset = 0;
9475 rsurface.batchtvector3f = NULL;
9476 rsurface.batchtvector3f_vertexbuffer = NULL;
9477 rsurface.batchtvector3f_bufferoffset = 0;
9478 rsurface.batchnormal3f = NULL;
9479 rsurface.batchnormal3f_vertexbuffer = NULL;
9480 rsurface.batchnormal3f_bufferoffset = 0;
9481 rsurface.batchlightmapcolor4f = NULL;
9482 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9483 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9484 rsurface.batchtexcoordtexture2f = NULL;
9485 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9486 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9487 rsurface.batchtexcoordlightmap2f = NULL;
9488 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9489 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9490 rsurface.batchskeletalindex4ub = NULL;
9491 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9492 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9493 rsurface.batchskeletalweight4ub = NULL;
9494 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9495 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9496 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9497 rsurface.batchelement3i_indexbuffer = NULL;
9498 rsurface.batchelement3i_bufferoffset = 0;
9499 rsurface.batchelement3s = NULL;
9500 rsurface.batchelement3s_indexbuffer = NULL;
9501 rsurface.batchelement3s_bufferoffset = 0;
9502 rsurface.batchskeletaltransform3x4buffer = NULL;
9503 rsurface.batchskeletaltransform3x4offset = 0;
9504 rsurface.batchskeletaltransform3x4size = 0;
9505 // we'll only be setting up certain arrays as needed
9506 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9507 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9508 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9509 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9510 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9511 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9512 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9514 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9515 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9517 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9518 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9519 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9520 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9521 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9522 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9523 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9525 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9526 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9530 for (i = 0;i < texturenumsurfaces;i++)
9532 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9533 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9534 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9535 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9536 // copy only the data requested
9537 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9538 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9539 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9541 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9543 if (rsurface.batchvertex3f)
9544 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9546 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9548 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9550 if (rsurface.modelnormal3f)
9551 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9553 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9555 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9557 if (rsurface.modelsvector3f)
9559 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9560 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9564 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9565 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9568 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9570 if (rsurface.modellightmapcolor4f)
9571 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9573 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9575 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9577 if (rsurface.modeltexcoordtexture2f)
9578 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9580 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9582 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9584 if (rsurface.modeltexcoordlightmap2f)
9585 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9587 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9589 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9591 if (rsurface.modelskeletalindex4ub)
9593 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9594 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9598 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9599 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9600 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9601 for (j = 0;j < surfacenumvertices;j++)
9606 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9607 numvertices += surfacenumvertices;
9608 numtriangles += surfacenumtriangles;
9611 // generate a 16bit index array as well if possible
9612 // (in general, dynamic batches fit)
9613 if (numvertices <= 65536)
9615 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9616 for (i = 0;i < numtriangles*3;i++)
9617 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9620 // since we've copied everything, the batch now starts at 0
9621 rsurface.batchfirstvertex = 0;
9622 rsurface.batchnumvertices = batchnumvertices;
9623 rsurface.batchfirsttriangle = 0;
9624 rsurface.batchnumtriangles = batchnumtriangles;
9627 // apply skeletal animation that would have been done in the vertex shader
9628 if (rsurface.batchskeletaltransform3x4)
9630 const unsigned char *si;
9631 const unsigned char *sw;
9633 const float *b = rsurface.batchskeletaltransform3x4;
9634 float *vp, *vs, *vt, *vn;
9636 float m[3][4], n[3][4];
9637 float tp[3], ts[3], tt[3], tn[3];
9638 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9639 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9640 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9641 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9642 si = rsurface.batchskeletalindex4ub;
9643 sw = rsurface.batchskeletalweight4ub;
9644 vp = rsurface.batchvertex3f;
9645 vs = rsurface.batchsvector3f;
9646 vt = rsurface.batchtvector3f;
9647 vn = rsurface.batchnormal3f;
9648 memset(m[0], 0, sizeof(m));
9649 memset(n[0], 0, sizeof(n));
9650 for (i = 0;i < batchnumvertices;i++)
9652 t[0] = b + si[0]*12;
9655 // common case - only one matrix
9669 else if (sw[2] + sw[3])
9672 t[1] = b + si[1]*12;
9673 t[2] = b + si[2]*12;
9674 t[3] = b + si[3]*12;
9675 w[0] = sw[0] * (1.0f / 255.0f);
9676 w[1] = sw[1] * (1.0f / 255.0f);
9677 w[2] = sw[2] * (1.0f / 255.0f);
9678 w[3] = sw[3] * (1.0f / 255.0f);
9679 // blend the matrices
9680 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9681 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9682 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9683 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9684 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9685 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9686 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9687 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9688 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9689 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9690 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9691 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9696 t[1] = b + si[1]*12;
9697 w[0] = sw[0] * (1.0f / 255.0f);
9698 w[1] = sw[1] * (1.0f / 255.0f);
9699 // blend the matrices
9700 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9701 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9702 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9703 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9704 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9705 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9706 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9707 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9708 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9709 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9710 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9711 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9715 // modify the vertex
9717 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9718 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9719 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9723 // the normal transformation matrix is a set of cross products...
9724 CrossProduct(m[1], m[2], n[0]);
9725 CrossProduct(m[2], m[0], n[1]);
9726 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9728 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9729 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9730 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9731 VectorNormalize(vn);
9736 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9737 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9738 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9739 VectorNormalize(vs);
9742 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9743 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9744 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9745 VectorNormalize(vt);
9750 rsurface.batchskeletaltransform3x4 = NULL;
9751 rsurface.batchskeletalnumtransforms = 0;
9754 // q1bsp surfaces rendered in vertex color mode have to have colors
9755 // calculated based on lightstyles
9756 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9758 // generate color arrays for the surfaces in this list
9763 const unsigned char *lm;
9764 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9765 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9766 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9768 for (i = 0;i < texturenumsurfaces;i++)
9770 surface = texturesurfacelist[i];
9771 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9772 surfacenumvertices = surface->num_vertices;
9773 if (surface->lightmapinfo->samples)
9775 for (j = 0;j < surfacenumvertices;j++)
9777 lm = surface->lightmapinfo->samples + offsets[j];
9778 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9779 VectorScale(lm, scale, c);
9780 if (surface->lightmapinfo->styles[1] != 255)
9782 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9784 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9785 VectorMA(c, scale, lm, c);
9786 if (surface->lightmapinfo->styles[2] != 255)
9789 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9790 VectorMA(c, scale, lm, c);
9791 if (surface->lightmapinfo->styles[3] != 255)
9794 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9795 VectorMA(c, scale, lm, c);
9802 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);
9808 for (j = 0;j < surfacenumvertices;j++)
9810 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9817 // if vertices are deformed (sprite flares and things in maps, possibly
9818 // water waves, bulges and other deformations), modify the copied vertices
9820 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9822 switch (deform->deform)
9825 case Q3DEFORM_PROJECTIONSHADOW:
9826 case Q3DEFORM_TEXT0:
9827 case Q3DEFORM_TEXT1:
9828 case Q3DEFORM_TEXT2:
9829 case Q3DEFORM_TEXT3:
9830 case Q3DEFORM_TEXT4:
9831 case Q3DEFORM_TEXT5:
9832 case Q3DEFORM_TEXT6:
9833 case Q3DEFORM_TEXT7:
9836 case Q3DEFORM_AUTOSPRITE:
9837 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9838 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9839 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9840 VectorNormalize(newforward);
9841 VectorNormalize(newright);
9842 VectorNormalize(newup);
9843 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9844 // rsurface.batchvertex3f_vertexbuffer = NULL;
9845 // rsurface.batchvertex3f_bufferoffset = 0;
9846 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9847 // rsurface.batchsvector3f_vertexbuffer = NULL;
9848 // rsurface.batchsvector3f_bufferoffset = 0;
9849 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9850 // rsurface.batchtvector3f_vertexbuffer = NULL;
9851 // rsurface.batchtvector3f_bufferoffset = 0;
9852 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9853 // rsurface.batchnormal3f_vertexbuffer = NULL;
9854 // rsurface.batchnormal3f_bufferoffset = 0;
9855 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9856 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9857 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9858 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9859 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);
9860 // a single autosprite surface can contain multiple sprites...
9861 for (j = 0;j < batchnumvertices - 3;j += 4)
9863 VectorClear(center);
9864 for (i = 0;i < 4;i++)
9865 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9866 VectorScale(center, 0.25f, center);
9867 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9868 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9869 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9870 for (i = 0;i < 4;i++)
9872 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9873 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9876 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9877 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9878 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);
9880 case Q3DEFORM_AUTOSPRITE2:
9881 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9882 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9883 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9884 VectorNormalize(newforward);
9885 VectorNormalize(newright);
9886 VectorNormalize(newup);
9887 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9888 // rsurface.batchvertex3f_vertexbuffer = NULL;
9889 // rsurface.batchvertex3f_bufferoffset = 0;
9891 const float *v1, *v2;
9901 memset(shortest, 0, sizeof(shortest));
9902 // a single autosprite surface can contain multiple sprites...
9903 for (j = 0;j < batchnumvertices - 3;j += 4)
9905 VectorClear(center);
9906 for (i = 0;i < 4;i++)
9907 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9908 VectorScale(center, 0.25f, center);
9909 // find the two shortest edges, then use them to define the
9910 // axis vectors for rotating around the central axis
9911 for (i = 0;i < 6;i++)
9913 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9914 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9915 l = VectorDistance2(v1, v2);
9916 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9918 l += (1.0f / 1024.0f);
9919 if (shortest[0].length2 > l || i == 0)
9921 shortest[1] = shortest[0];
9922 shortest[0].length2 = l;
9923 shortest[0].v1 = v1;
9924 shortest[0].v2 = v2;
9926 else if (shortest[1].length2 > l || i == 1)
9928 shortest[1].length2 = l;
9929 shortest[1].v1 = v1;
9930 shortest[1].v2 = v2;
9933 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9934 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9935 // this calculates the right vector from the shortest edge
9936 // and the up vector from the edge midpoints
9937 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9938 VectorNormalize(right);
9939 VectorSubtract(end, start, up);
9940 VectorNormalize(up);
9941 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9942 VectorSubtract(rsurface.localvieworigin, center, forward);
9943 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9944 VectorNegate(forward, forward);
9945 VectorReflect(forward, 0, up, forward);
9946 VectorNormalize(forward);
9947 CrossProduct(up, forward, newright);
9948 VectorNormalize(newright);
9949 // rotate the quad around the up axis vector, this is made
9950 // especially easy by the fact we know the quad is flat,
9951 // so we only have to subtract the center position and
9952 // measure distance along the right vector, and then
9953 // multiply that by the newright vector and add back the
9955 // we also need to subtract the old position to undo the
9956 // displacement from the center, which we do with a
9957 // DotProduct, the subtraction/addition of center is also
9958 // optimized into DotProducts here
9959 l = DotProduct(right, center);
9960 for (i = 0;i < 4;i++)
9962 v1 = rsurface.batchvertex3f + 3*(j+i);
9963 f = DotProduct(right, v1) - l;
9964 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9968 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9970 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9971 // rsurface.batchnormal3f_vertexbuffer = NULL;
9972 // rsurface.batchnormal3f_bufferoffset = 0;
9973 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9975 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9977 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9978 // rsurface.batchsvector3f_vertexbuffer = NULL;
9979 // rsurface.batchsvector3f_bufferoffset = 0;
9980 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9981 // rsurface.batchtvector3f_vertexbuffer = NULL;
9982 // rsurface.batchtvector3f_bufferoffset = 0;
9983 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);
9986 case Q3DEFORM_NORMAL:
9987 // deform the normals to make reflections wavey
9988 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9989 rsurface.batchnormal3f_vertexbuffer = NULL;
9990 rsurface.batchnormal3f_bufferoffset = 0;
9991 for (j = 0;j < batchnumvertices;j++)
9994 float *normal = rsurface.batchnormal3f + 3*j;
9995 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9996 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9997 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9998 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9999 VectorNormalize(normal);
10001 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10003 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10004 // rsurface.batchsvector3f_vertexbuffer = NULL;
10005 // rsurface.batchsvector3f_bufferoffset = 0;
10006 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10007 // rsurface.batchtvector3f_vertexbuffer = NULL;
10008 // rsurface.batchtvector3f_bufferoffset = 0;
10009 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);
10012 case Q3DEFORM_WAVE:
10013 // deform vertex array to make wavey water and flags and such
10014 waveparms[0] = deform->waveparms[0];
10015 waveparms[1] = deform->waveparms[1];
10016 waveparms[2] = deform->waveparms[2];
10017 waveparms[3] = deform->waveparms[3];
10018 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10019 break; // if wavefunc is a nop, don't make a dynamic vertex array
10020 // this is how a divisor of vertex influence on deformation
10021 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10022 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10023 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10024 // rsurface.batchvertex3f_vertexbuffer = NULL;
10025 // rsurface.batchvertex3f_bufferoffset = 0;
10026 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10027 // rsurface.batchnormal3f_vertexbuffer = NULL;
10028 // rsurface.batchnormal3f_bufferoffset = 0;
10029 for (j = 0;j < batchnumvertices;j++)
10031 // if the wavefunc depends on time, evaluate it per-vertex
10034 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10035 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10037 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10039 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10040 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10041 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10043 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10044 // rsurface.batchsvector3f_vertexbuffer = NULL;
10045 // rsurface.batchsvector3f_bufferoffset = 0;
10046 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10047 // rsurface.batchtvector3f_vertexbuffer = NULL;
10048 // rsurface.batchtvector3f_bufferoffset = 0;
10049 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);
10052 case Q3DEFORM_BULGE:
10053 // deform vertex array to make the surface have moving bulges
10054 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10055 // rsurface.batchvertex3f_vertexbuffer = NULL;
10056 // rsurface.batchvertex3f_bufferoffset = 0;
10057 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10058 // rsurface.batchnormal3f_vertexbuffer = NULL;
10059 // rsurface.batchnormal3f_bufferoffset = 0;
10060 for (j = 0;j < batchnumvertices;j++)
10062 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10063 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10065 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10066 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10067 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10069 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10070 // rsurface.batchsvector3f_vertexbuffer = NULL;
10071 // rsurface.batchsvector3f_bufferoffset = 0;
10072 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10073 // rsurface.batchtvector3f_vertexbuffer = NULL;
10074 // rsurface.batchtvector3f_bufferoffset = 0;
10075 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);
10078 case Q3DEFORM_MOVE:
10079 // deform vertex array
10080 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10081 break; // if wavefunc is a nop, don't make a dynamic vertex array
10082 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10083 VectorScale(deform->parms, scale, waveparms);
10084 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10085 // rsurface.batchvertex3f_vertexbuffer = NULL;
10086 // rsurface.batchvertex3f_bufferoffset = 0;
10087 for (j = 0;j < batchnumvertices;j++)
10088 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10093 if (rsurface.batchtexcoordtexture2f)
10095 // generate texcoords based on the chosen texcoord source
10096 switch(rsurface.texture->tcgen.tcgen)
10099 case Q3TCGEN_TEXTURE:
10101 case Q3TCGEN_LIGHTMAP:
10102 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10103 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10104 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10105 if (rsurface.batchtexcoordlightmap2f)
10106 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10108 case Q3TCGEN_VECTOR:
10109 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10110 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10111 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10112 for (j = 0;j < batchnumvertices;j++)
10114 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10115 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10118 case Q3TCGEN_ENVIRONMENT:
10119 // make environment reflections using a spheremap
10120 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10121 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10122 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10123 for (j = 0;j < batchnumvertices;j++)
10125 // identical to Q3A's method, but executed in worldspace so
10126 // carried models can be shiny too
10128 float viewer[3], d, reflected[3], worldreflected[3];
10130 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10131 // VectorNormalize(viewer);
10133 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10135 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10136 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10137 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10138 // note: this is proportinal to viewer, so we can normalize later
10140 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10141 VectorNormalize(worldreflected);
10143 // note: this sphere map only uses world x and z!
10144 // so positive and negative y will LOOK THE SAME.
10145 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10146 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10150 // the only tcmod that needs software vertex processing is turbulent, so
10151 // check for it here and apply the changes if needed
10152 // and we only support that as the first one
10153 // (handling a mixture of turbulent and other tcmods would be problematic
10154 // without punting it entirely to a software path)
10155 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10157 amplitude = rsurface.texture->tcmods[0].parms[1];
10158 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10159 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10160 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10161 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10162 for (j = 0;j < batchnumvertices;j++)
10164 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);
10165 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10170 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10172 // convert the modified arrays to vertex structs
10173 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10174 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10175 // rsurface.batchvertexmesh_bufferoffset = 0;
10176 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10177 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10178 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10179 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10180 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10181 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10182 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10184 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10186 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10187 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10190 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10191 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10192 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10193 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10194 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10195 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10196 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10197 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10198 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10199 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10201 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10203 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10204 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10209 // upload buffer data for the dynamic batch
10210 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10212 if (rsurface.batchvertexmesh)
10213 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10216 if (rsurface.batchvertex3f)
10217 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10218 if (rsurface.batchsvector3f)
10219 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10220 if (rsurface.batchtvector3f)
10221 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10222 if (rsurface.batchnormal3f)
10223 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10224 if (rsurface.batchlightmapcolor4f)
10225 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10226 if (rsurface.batchtexcoordtexture2f)
10227 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10228 if (rsurface.batchtexcoordlightmap2f)
10229 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10230 if (rsurface.batchskeletalindex4ub)
10231 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10232 if (rsurface.batchskeletalweight4ub)
10233 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10235 if (rsurface.batchelement3s)
10236 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10237 else if (rsurface.batchelement3i)
10238 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10242 void RSurf_DrawBatch(void)
10244 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10245 // through the pipeline, killing it earlier in the pipeline would have
10246 // per-surface overhead rather than per-batch overhead, so it's best to
10247 // reject it here, before it hits glDraw.
10248 if (rsurface.batchnumtriangles == 0)
10251 // batch debugging code
10252 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10258 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10259 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10262 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10264 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10266 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10267 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);
10274 if (rsurface.batchmultidraw)
10276 // issue multiple draws rather than copying index data
10277 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10278 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10279 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10280 for (i = 0;i < numsurfaces;)
10282 // combine consecutive surfaces as one draw
10283 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10284 if (surfacelist[j] != surfacelist[k] + 1)
10286 firstvertex = surfacelist[i]->num_firstvertex;
10287 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10288 firsttriangle = surfacelist[i]->num_firsttriangle;
10289 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10290 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);
10296 // there is only one consecutive run of index data (may have been combined)
10297 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);
10301 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10303 // pick the closest matching water plane
10304 int planeindex, vertexindex, bestplaneindex = -1;
10308 r_waterstate_waterplane_t *p;
10309 qboolean prepared = false;
10311 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10313 if(p->camera_entity != rsurface.texture->camera_entity)
10318 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10320 if(rsurface.batchnumvertices == 0)
10323 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10325 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10326 d += fabs(PlaneDiff(vert, &p->plane));
10328 if (bestd > d || bestplaneindex < 0)
10331 bestplaneindex = planeindex;
10334 return bestplaneindex;
10335 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10336 // this situation though, as it might be better to render single larger
10337 // batches with useless stuff (backface culled for example) than to
10338 // render multiple smaller batches
10341 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10344 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10345 rsurface.passcolor4f_vertexbuffer = 0;
10346 rsurface.passcolor4f_bufferoffset = 0;
10347 for (i = 0;i < rsurface.batchnumvertices;i++)
10348 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10351 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10358 if (rsurface.passcolor4f)
10360 // generate color arrays
10361 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10362 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10363 rsurface.passcolor4f_vertexbuffer = 0;
10364 rsurface.passcolor4f_bufferoffset = 0;
10365 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)
10367 f = RSurf_FogVertex(v);
10376 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10377 rsurface.passcolor4f_vertexbuffer = 0;
10378 rsurface.passcolor4f_bufferoffset = 0;
10379 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10381 f = RSurf_FogVertex(v);
10390 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10397 if (!rsurface.passcolor4f)
10399 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10400 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10401 rsurface.passcolor4f_vertexbuffer = 0;
10402 rsurface.passcolor4f_bufferoffset = 0;
10403 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)
10405 f = RSurf_FogVertex(v);
10406 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10407 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10408 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10413 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
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)
10433 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10438 if (!rsurface.passcolor4f)
10440 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10441 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10442 rsurface.passcolor4f_vertexbuffer = 0;
10443 rsurface.passcolor4f_bufferoffset = 0;
10444 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10446 c2[0] = c[0] + r_refdef.scene.ambient;
10447 c2[1] = c[1] + r_refdef.scene.ambient;
10448 c2[2] = c[2] + r_refdef.scene.ambient;
10453 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10456 rsurface.passcolor4f = NULL;
10457 rsurface.passcolor4f_vertexbuffer = 0;
10458 rsurface.passcolor4f_bufferoffset = 0;
10459 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10460 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10461 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10462 GL_Color(r, g, b, a);
10463 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10464 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10465 R_Mesh_TexMatrix(0, NULL);
10469 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10471 // TODO: optimize applyfog && applycolor case
10472 // just apply fog if necessary, and tint the fog color array if necessary
10473 rsurface.passcolor4f = NULL;
10474 rsurface.passcolor4f_vertexbuffer = 0;
10475 rsurface.passcolor4f_bufferoffset = 0;
10476 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10477 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10478 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10479 GL_Color(r, g, b, a);
10483 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10486 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10487 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10488 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10489 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10490 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10491 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10492 GL_Color(r, g, b, a);
10496 static void RSurf_DrawBatch_GL11_ClampColor(void)
10501 if (!rsurface.passcolor4f)
10503 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10505 c2[0] = bound(0.0f, c1[0], 1.0f);
10506 c2[1] = bound(0.0f, c1[1], 1.0f);
10507 c2[2] = bound(0.0f, c1[2], 1.0f);
10508 c2[3] = bound(0.0f, c1[3], 1.0f);
10512 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10522 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10523 rsurface.passcolor4f_vertexbuffer = 0;
10524 rsurface.passcolor4f_bufferoffset = 0;
10525 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)
10527 f = -DotProduct(r_refdef.view.forward, n);
10529 f = f * 0.85 + 0.15; // work around so stuff won't get black
10530 f *= r_refdef.lightmapintensity;
10531 Vector4Set(c, f, f, f, 1);
10535 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10537 RSurf_DrawBatch_GL11_ApplyFakeLight();
10538 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10539 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10540 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10541 GL_Color(r, g, b, a);
10545 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10553 vec3_t ambientcolor;
10554 vec3_t diffusecolor;
10558 VectorCopy(rsurface.modellight_lightdir, lightdir);
10559 f = 0.5f * r_refdef.lightmapintensity;
10560 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10561 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10562 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10563 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10564 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10565 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10567 if (VectorLength2(diffusecolor) > 0)
10569 // q3-style directional shading
10570 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10571 rsurface.passcolor4f_vertexbuffer = 0;
10572 rsurface.passcolor4f_bufferoffset = 0;
10573 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)
10575 if ((f = DotProduct(n, lightdir)) > 0)
10576 VectorMA(ambientcolor, f, diffusecolor, c);
10578 VectorCopy(ambientcolor, c);
10585 *applycolor = false;
10589 *r = ambientcolor[0];
10590 *g = ambientcolor[1];
10591 *b = ambientcolor[2];
10592 rsurface.passcolor4f = NULL;
10593 rsurface.passcolor4f_vertexbuffer = 0;
10594 rsurface.passcolor4f_bufferoffset = 0;
10598 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10600 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10601 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10602 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10603 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10604 GL_Color(r, g, b, a);
10608 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10616 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10617 rsurface.passcolor4f_vertexbuffer = 0;
10618 rsurface.passcolor4f_bufferoffset = 0;
10620 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10622 f = 1 - RSurf_FogVertex(v);
10630 void RSurf_SetupDepthAndCulling(void)
10632 // submodels are biased to avoid z-fighting with world surfaces that they
10633 // may be exactly overlapping (avoids z-fighting artifacts on certain
10634 // doors and things in Quake maps)
10635 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10636 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10637 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10638 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10641 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10643 // transparent sky would be ridiculous
10644 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10646 R_SetupShader_Generic_NoTexture(false, false);
10647 skyrenderlater = true;
10648 RSurf_SetupDepthAndCulling();
10649 GL_DepthMask(true);
10650 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10651 // skymasking on them, and Quake3 never did sky masking (unlike
10652 // software Quake and software Quake2), so disable the sky masking
10653 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10654 // and skymasking also looks very bad when noclipping outside the
10655 // level, so don't use it then either.
10656 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10658 R_Mesh_ResetTextureState();
10659 if (skyrendermasked)
10661 R_SetupShader_DepthOrShadow(false, false, false);
10662 // depth-only (masking)
10663 GL_ColorMask(0,0,0,0);
10664 // just to make sure that braindead drivers don't draw
10665 // anything despite that colormask...
10666 GL_BlendFunc(GL_ZERO, GL_ONE);
10667 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10668 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10672 R_SetupShader_Generic_NoTexture(false, false);
10674 GL_BlendFunc(GL_ONE, GL_ZERO);
10675 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10676 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10677 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10680 if (skyrendermasked)
10681 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10683 R_Mesh_ResetTextureState();
10684 GL_Color(1, 1, 1, 1);
10687 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10688 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10689 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10691 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10695 // render screenspace normalmap to texture
10696 GL_DepthMask(true);
10697 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10702 // bind lightmap texture
10704 // water/refraction/reflection/camera surfaces have to be handled specially
10705 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10707 int start, end, startplaneindex;
10708 for (start = 0;start < texturenumsurfaces;start = end)
10710 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10711 if(startplaneindex < 0)
10713 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10714 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10718 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10720 // now that we have a batch using the same planeindex, render it
10721 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10723 // render water or distortion background
10724 GL_DepthMask(true);
10725 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);
10727 // blend surface on top
10728 GL_DepthMask(false);
10729 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10732 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10734 // render surface with reflection texture as input
10735 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10736 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);
10743 // render surface batch normally
10744 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10745 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);
10749 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10751 // OpenGL 1.3 path - anything not completely ancient
10752 qboolean applycolor;
10755 const texturelayer_t *layer;
10756 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);
10757 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10759 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10762 int layertexrgbscale;
10763 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10765 if (layerindex == 0)
10766 GL_AlphaTest(true);
10769 GL_AlphaTest(false);
10770 GL_DepthFunc(GL_EQUAL);
10773 GL_DepthMask(layer->depthmask && writedepth);
10774 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10775 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10777 layertexrgbscale = 4;
10778 VectorScale(layer->color, 0.25f, layercolor);
10780 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10782 layertexrgbscale = 2;
10783 VectorScale(layer->color, 0.5f, layercolor);
10787 layertexrgbscale = 1;
10788 VectorScale(layer->color, 1.0f, layercolor);
10790 layercolor[3] = layer->color[3];
10791 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10792 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10793 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10794 switch (layer->type)
10796 case TEXTURELAYERTYPE_LITTEXTURE:
10797 // single-pass lightmapped texture with 2x rgbscale
10798 R_Mesh_TexBind(0, r_texture_white);
10799 R_Mesh_TexMatrix(0, NULL);
10800 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10801 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10802 R_Mesh_TexBind(1, layer->texture);
10803 R_Mesh_TexMatrix(1, &layer->texmatrix);
10804 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10805 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10806 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10807 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10808 else if (FAKELIGHT_ENABLED)
10809 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10810 else if (rsurface.uselightmaptexture)
10811 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10813 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10815 case TEXTURELAYERTYPE_TEXTURE:
10816 // singletexture unlit texture with transparency support
10817 R_Mesh_TexBind(0, layer->texture);
10818 R_Mesh_TexMatrix(0, &layer->texmatrix);
10819 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10820 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10821 R_Mesh_TexBind(1, 0);
10822 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10823 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10825 case TEXTURELAYERTYPE_FOG:
10826 // singletexture fogging
10827 if (layer->texture)
10829 R_Mesh_TexBind(0, layer->texture);
10830 R_Mesh_TexMatrix(0, &layer->texmatrix);
10831 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10832 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10836 R_Mesh_TexBind(0, 0);
10837 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10839 R_Mesh_TexBind(1, 0);
10840 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10841 // generate a color array for the fog pass
10842 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10843 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10847 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10850 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10852 GL_DepthFunc(GL_LEQUAL);
10853 GL_AlphaTest(false);
10857 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10859 // OpenGL 1.1 - crusty old voodoo path
10862 const texturelayer_t *layer;
10863 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);
10864 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10866 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10868 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10870 if (layerindex == 0)
10871 GL_AlphaTest(true);
10874 GL_AlphaTest(false);
10875 GL_DepthFunc(GL_EQUAL);
10878 GL_DepthMask(layer->depthmask && writedepth);
10879 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10880 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10881 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10882 switch (layer->type)
10884 case TEXTURELAYERTYPE_LITTEXTURE:
10885 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10887 // two-pass lit texture with 2x rgbscale
10888 // first the lightmap pass
10889 R_Mesh_TexBind(0, r_texture_white);
10890 R_Mesh_TexMatrix(0, NULL);
10891 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10892 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10893 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10894 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10895 else if (FAKELIGHT_ENABLED)
10896 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10897 else if (rsurface.uselightmaptexture)
10898 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10900 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10901 // then apply the texture to it
10902 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10903 R_Mesh_TexBind(0, layer->texture);
10904 R_Mesh_TexMatrix(0, &layer->texmatrix);
10905 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10906 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10907 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);
10911 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10912 R_Mesh_TexBind(0, layer->texture);
10913 R_Mesh_TexMatrix(0, &layer->texmatrix);
10914 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10915 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10916 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10917 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);
10918 else if (FAKELIGHT_ENABLED)
10919 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);
10921 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);
10924 case TEXTURELAYERTYPE_TEXTURE:
10925 // singletexture unlit texture with transparency support
10926 R_Mesh_TexBind(0, layer->texture);
10927 R_Mesh_TexMatrix(0, &layer->texmatrix);
10928 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10929 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10930 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);
10932 case TEXTURELAYERTYPE_FOG:
10933 // singletexture fogging
10934 if (layer->texture)
10936 R_Mesh_TexBind(0, layer->texture);
10937 R_Mesh_TexMatrix(0, &layer->texmatrix);
10938 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10939 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10943 R_Mesh_TexBind(0, 0);
10944 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10946 // generate a color array for the fog pass
10947 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10948 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10952 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10955 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10957 GL_DepthFunc(GL_LEQUAL);
10958 GL_AlphaTest(false);
10962 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10966 r_vertexgeneric_t *batchvertex;
10969 // R_Mesh_ResetTextureState();
10970 R_SetupShader_Generic_NoTexture(false, false);
10972 if(rsurface.texture && rsurface.texture->currentskinframe)
10974 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10975 c[3] *= rsurface.texture->currentalpha;
10985 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10987 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10988 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10989 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10992 // brighten it up (as texture value 127 means "unlit")
10993 c[0] *= 2 * r_refdef.view.colorscale;
10994 c[1] *= 2 * r_refdef.view.colorscale;
10995 c[2] *= 2 * r_refdef.view.colorscale;
10997 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10998 c[3] *= r_wateralpha.value;
11000 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11002 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11003 GL_DepthMask(false);
11005 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11007 GL_BlendFunc(GL_ONE, GL_ONE);
11008 GL_DepthMask(false);
11010 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11012 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11013 GL_DepthMask(false);
11015 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11017 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11018 GL_DepthMask(false);
11022 GL_BlendFunc(GL_ONE, GL_ZERO);
11023 GL_DepthMask(writedepth);
11026 if (r_showsurfaces.integer == 3)
11028 rsurface.passcolor4f = NULL;
11030 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11032 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11034 rsurface.passcolor4f = NULL;
11035 rsurface.passcolor4f_vertexbuffer = 0;
11036 rsurface.passcolor4f_bufferoffset = 0;
11038 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11040 qboolean applycolor = true;
11043 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11045 r_refdef.lightmapintensity = 1;
11046 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11047 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11049 else if (FAKELIGHT_ENABLED)
11051 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11053 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11054 RSurf_DrawBatch_GL11_ApplyFakeLight();
11055 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11059 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11061 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11062 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11063 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11066 if(!rsurface.passcolor4f)
11067 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11069 RSurf_DrawBatch_GL11_ApplyAmbient();
11070 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11071 if(r_refdef.fogenabled)
11072 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11073 RSurf_DrawBatch_GL11_ClampColor();
11075 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11076 R_SetupShader_Generic_NoTexture(false, false);
11079 else if (!r_refdef.view.showdebug)
11081 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11082 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11083 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11085 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11086 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11088 R_Mesh_PrepareVertices_Generic_Unlock();
11091 else if (r_showsurfaces.integer == 4)
11093 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11094 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11095 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11097 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11098 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11099 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11101 R_Mesh_PrepareVertices_Generic_Unlock();
11104 else if (r_showsurfaces.integer == 2)
11107 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11108 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11109 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11111 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11112 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11113 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11114 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11115 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11116 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11117 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11119 R_Mesh_PrepareVertices_Generic_Unlock();
11120 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11124 int texturesurfaceindex;
11126 const msurface_t *surface;
11127 float surfacecolor4f[4];
11128 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11129 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11131 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11133 surface = texturesurfacelist[texturesurfaceindex];
11134 k = (int)(((size_t)surface) / sizeof(msurface_t));
11135 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11136 for (j = 0;j < surface->num_vertices;j++)
11138 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11139 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11143 R_Mesh_PrepareVertices_Generic_Unlock();
11148 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11151 RSurf_SetupDepthAndCulling();
11152 if (r_showsurfaces.integer)
11154 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11157 switch (vid.renderpath)
11159 case RENDERPATH_GL20:
11160 case RENDERPATH_D3D9:
11161 case RENDERPATH_D3D10:
11162 case RENDERPATH_D3D11:
11163 case RENDERPATH_SOFT:
11164 case RENDERPATH_GLES2:
11165 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11167 case RENDERPATH_GL13:
11168 case RENDERPATH_GLES1:
11169 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11171 case RENDERPATH_GL11:
11172 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11178 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11181 RSurf_SetupDepthAndCulling();
11182 if (r_showsurfaces.integer)
11184 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11187 switch (vid.renderpath)
11189 case RENDERPATH_GL20:
11190 case RENDERPATH_D3D9:
11191 case RENDERPATH_D3D10:
11192 case RENDERPATH_D3D11:
11193 case RENDERPATH_SOFT:
11194 case RENDERPATH_GLES2:
11195 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11197 case RENDERPATH_GL13:
11198 case RENDERPATH_GLES1:
11199 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11201 case RENDERPATH_GL11:
11202 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11208 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11211 int texturenumsurfaces, endsurface;
11212 texture_t *texture;
11213 const msurface_t *surface;
11214 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11216 // if the model is static it doesn't matter what value we give for
11217 // wantnormals and wanttangents, so this logic uses only rules applicable
11218 // to a model, knowing that they are meaningless otherwise
11219 if (ent == r_refdef.scene.worldentity)
11220 RSurf_ActiveWorldEntity();
11221 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11222 RSurf_ActiveModelEntity(ent, false, false, false);
11225 switch (vid.renderpath)
11227 case RENDERPATH_GL20:
11228 case RENDERPATH_D3D9:
11229 case RENDERPATH_D3D10:
11230 case RENDERPATH_D3D11:
11231 case RENDERPATH_SOFT:
11232 case RENDERPATH_GLES2:
11233 RSurf_ActiveModelEntity(ent, true, true, false);
11235 case RENDERPATH_GL11:
11236 case RENDERPATH_GL13:
11237 case RENDERPATH_GLES1:
11238 RSurf_ActiveModelEntity(ent, true, false, false);
11243 if (r_transparentdepthmasking.integer)
11245 qboolean setup = false;
11246 for (i = 0;i < numsurfaces;i = j)
11249 surface = rsurface.modelsurfaces + surfacelist[i];
11250 texture = surface->texture;
11251 rsurface.texture = R_GetCurrentTexture(texture);
11252 rsurface.lightmaptexture = NULL;
11253 rsurface.deluxemaptexture = NULL;
11254 rsurface.uselightmaptexture = false;
11255 // scan ahead until we find a different texture
11256 endsurface = min(i + 1024, numsurfaces);
11257 texturenumsurfaces = 0;
11258 texturesurfacelist[texturenumsurfaces++] = surface;
11259 for (;j < endsurface;j++)
11261 surface = rsurface.modelsurfaces + surfacelist[j];
11262 if (texture != surface->texture)
11264 texturesurfacelist[texturenumsurfaces++] = surface;
11266 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11268 // render the range of surfaces as depth
11272 GL_ColorMask(0,0,0,0);
11274 GL_DepthTest(true);
11275 GL_BlendFunc(GL_ONE, GL_ZERO);
11276 GL_DepthMask(true);
11277 // R_Mesh_ResetTextureState();
11279 RSurf_SetupDepthAndCulling();
11280 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11281 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11282 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11286 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11289 for (i = 0;i < numsurfaces;i = j)
11292 surface = rsurface.modelsurfaces + surfacelist[i];
11293 texture = surface->texture;
11294 rsurface.texture = R_GetCurrentTexture(texture);
11295 // scan ahead until we find a different texture
11296 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11297 texturenumsurfaces = 0;
11298 texturesurfacelist[texturenumsurfaces++] = surface;
11299 if(FAKELIGHT_ENABLED)
11301 rsurface.lightmaptexture = NULL;
11302 rsurface.deluxemaptexture = NULL;
11303 rsurface.uselightmaptexture = false;
11304 for (;j < endsurface;j++)
11306 surface = rsurface.modelsurfaces + surfacelist[j];
11307 if (texture != surface->texture)
11309 texturesurfacelist[texturenumsurfaces++] = surface;
11314 rsurface.lightmaptexture = surface->lightmaptexture;
11315 rsurface.deluxemaptexture = surface->deluxemaptexture;
11316 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11317 for (;j < endsurface;j++)
11319 surface = rsurface.modelsurfaces + surfacelist[j];
11320 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11322 texturesurfacelist[texturenumsurfaces++] = surface;
11325 // render the range of surfaces
11326 if (ent == r_refdef.scene.worldentity)
11327 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11329 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11331 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11334 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11336 // transparent surfaces get pushed off into the transparent queue
11337 int surfacelistindex;
11338 const msurface_t *surface;
11339 vec3_t tempcenter, center;
11340 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11342 surface = texturesurfacelist[surfacelistindex];
11343 if (r_transparent_sortsurfacesbynearest.integer)
11345 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11346 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11347 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11351 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11352 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11353 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11355 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11356 if (rsurface.entity->transparent_offset) // transparent offset
11358 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11359 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11360 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11362 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);
11366 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11368 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11370 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11372 RSurf_SetupDepthAndCulling();
11373 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11374 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11375 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11379 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11383 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11386 if (!rsurface.texture->currentnumlayers)
11388 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11389 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11391 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11393 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11394 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11395 else if (!rsurface.texture->currentnumlayers)
11397 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11399 // in the deferred case, transparent surfaces were queued during prepass
11400 if (!r_shadow_usingdeferredprepass)
11401 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11405 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11406 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11411 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11414 texture_t *texture;
11415 R_FrameData_SetMark();
11416 // break the surface list down into batches by texture and use of lightmapping
11417 for (i = 0;i < numsurfaces;i = j)
11420 // texture is the base texture pointer, rsurface.texture is the
11421 // current frame/skin the texture is directing us to use (for example
11422 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11423 // use skin 1 instead)
11424 texture = surfacelist[i]->texture;
11425 rsurface.texture = R_GetCurrentTexture(texture);
11426 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11428 // if this texture is not the kind we want, skip ahead to the next one
11429 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11433 if(FAKELIGHT_ENABLED || depthonly || prepass)
11435 rsurface.lightmaptexture = NULL;
11436 rsurface.deluxemaptexture = NULL;
11437 rsurface.uselightmaptexture = false;
11438 // simply scan ahead until we find a different texture or lightmap state
11439 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11444 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11445 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11446 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11447 // simply scan ahead until we find a different texture or lightmap state
11448 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11451 // render the range of surfaces
11452 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11454 R_FrameData_ReturnToMark();
11457 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11461 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11464 if (!rsurface.texture->currentnumlayers)
11466 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11467 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11469 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11471 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11472 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11473 else if (!rsurface.texture->currentnumlayers)
11475 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11477 // in the deferred case, transparent surfaces were queued during prepass
11478 if (!r_shadow_usingdeferredprepass)
11479 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11483 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11484 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11489 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11492 texture_t *texture;
11493 R_FrameData_SetMark();
11494 // break the surface list down into batches by texture and use of lightmapping
11495 for (i = 0;i < numsurfaces;i = j)
11498 // texture is the base texture pointer, rsurface.texture is the
11499 // current frame/skin the texture is directing us to use (for example
11500 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11501 // use skin 1 instead)
11502 texture = surfacelist[i]->texture;
11503 rsurface.texture = R_GetCurrentTexture(texture);
11504 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11506 // if this texture is not the kind we want, skip ahead to the next one
11507 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11511 if(FAKELIGHT_ENABLED || depthonly || prepass)
11513 rsurface.lightmaptexture = NULL;
11514 rsurface.deluxemaptexture = NULL;
11515 rsurface.uselightmaptexture = false;
11516 // simply scan ahead until we find a different texture or lightmap state
11517 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11522 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11523 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11524 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11525 // simply scan ahead until we find a different texture or lightmap state
11526 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11529 // render the range of surfaces
11530 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11532 R_FrameData_ReturnToMark();
11535 float locboxvertex3f[6*4*3] =
11537 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11538 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11539 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11540 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11541 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11542 1,0,0, 0,0,0, 0,1,0, 1,1,0
11545 unsigned short locboxelements[6*2*3] =
11550 12,13,14, 12,14,15,
11551 16,17,18, 16,18,19,
11555 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11558 cl_locnode_t *loc = (cl_locnode_t *)ent;
11560 float vertex3f[6*4*3];
11562 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11563 GL_DepthMask(false);
11564 GL_DepthRange(0, 1);
11565 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11566 GL_DepthTest(true);
11567 GL_CullFace(GL_NONE);
11568 R_EntityMatrix(&identitymatrix);
11570 // R_Mesh_ResetTextureState();
11572 i = surfacelist[0];
11573 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11574 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11575 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11576 surfacelist[0] < 0 ? 0.5f : 0.125f);
11578 if (VectorCompare(loc->mins, loc->maxs))
11580 VectorSet(size, 2, 2, 2);
11581 VectorMA(loc->mins, -0.5f, size, mins);
11585 VectorCopy(loc->mins, mins);
11586 VectorSubtract(loc->maxs, loc->mins, size);
11589 for (i = 0;i < 6*4*3;)
11590 for (j = 0;j < 3;j++, i++)
11591 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11593 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11594 R_SetupShader_Generic_NoTexture(false, false);
11595 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11598 void R_DrawLocs(void)
11601 cl_locnode_t *loc, *nearestloc;
11603 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11604 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11606 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11607 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11611 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11613 if (decalsystem->decals)
11614 Mem_Free(decalsystem->decals);
11615 memset(decalsystem, 0, sizeof(*decalsystem));
11618 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)
11621 tridecal_t *decals;
11624 // expand or initialize the system
11625 if (decalsystem->maxdecals <= decalsystem->numdecals)
11627 decalsystem_t old = *decalsystem;
11628 qboolean useshortelements;
11629 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11630 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11631 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)));
11632 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11633 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11634 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11635 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11636 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11637 if (decalsystem->numdecals)
11638 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11640 Mem_Free(old.decals);
11641 for (i = 0;i < decalsystem->maxdecals*3;i++)
11642 decalsystem->element3i[i] = i;
11643 if (useshortelements)
11644 for (i = 0;i < decalsystem->maxdecals*3;i++)
11645 decalsystem->element3s[i] = i;
11648 // grab a decal and search for another free slot for the next one
11649 decals = decalsystem->decals;
11650 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11651 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11653 decalsystem->freedecal = i;
11654 if (decalsystem->numdecals <= i)
11655 decalsystem->numdecals = i + 1;
11657 // initialize the decal
11659 decal->triangleindex = triangleindex;
11660 decal->surfaceindex = surfaceindex;
11661 decal->decalsequence = decalsequence;
11662 decal->color4f[0][0] = c0[0];
11663 decal->color4f[0][1] = c0[1];
11664 decal->color4f[0][2] = c0[2];
11665 decal->color4f[0][3] = 1;
11666 decal->color4f[1][0] = c1[0];
11667 decal->color4f[1][1] = c1[1];
11668 decal->color4f[1][2] = c1[2];
11669 decal->color4f[1][3] = 1;
11670 decal->color4f[2][0] = c2[0];
11671 decal->color4f[2][1] = c2[1];
11672 decal->color4f[2][2] = c2[2];
11673 decal->color4f[2][3] = 1;
11674 decal->vertex3f[0][0] = v0[0];
11675 decal->vertex3f[0][1] = v0[1];
11676 decal->vertex3f[0][2] = v0[2];
11677 decal->vertex3f[1][0] = v1[0];
11678 decal->vertex3f[1][1] = v1[1];
11679 decal->vertex3f[1][2] = v1[2];
11680 decal->vertex3f[2][0] = v2[0];
11681 decal->vertex3f[2][1] = v2[1];
11682 decal->vertex3f[2][2] = v2[2];
11683 decal->texcoord2f[0][0] = t0[0];
11684 decal->texcoord2f[0][1] = t0[1];
11685 decal->texcoord2f[1][0] = t1[0];
11686 decal->texcoord2f[1][1] = t1[1];
11687 decal->texcoord2f[2][0] = t2[0];
11688 decal->texcoord2f[2][1] = t2[1];
11689 TriangleNormal(v0, v1, v2, decal->plane);
11690 VectorNormalize(decal->plane);
11691 decal->plane[3] = DotProduct(v0, decal->plane);
11694 extern cvar_t cl_decals_bias;
11695 extern cvar_t cl_decals_models;
11696 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11697 // baseparms, parms, temps
11698 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)
11703 const float *vertex3f;
11704 const float *normal3f;
11706 float points[2][9][3];
11713 e = rsurface.modelelement3i + 3*triangleindex;
11715 vertex3f = rsurface.modelvertex3f;
11716 normal3f = rsurface.modelnormal3f;
11720 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11722 index = 3*e[cornerindex];
11723 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11728 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11730 index = 3*e[cornerindex];
11731 VectorCopy(vertex3f + index, v[cornerindex]);
11736 //TriangleNormal(v[0], v[1], v[2], normal);
11737 //if (DotProduct(normal, localnormal) < 0.0f)
11739 // clip by each of the box planes formed from the projection matrix
11740 // if anything survives, we emit the decal
11741 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]);
11744 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]);
11747 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]);
11750 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]);
11753 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]);
11756 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]);
11759 // some part of the triangle survived, so we have to accept it...
11762 // dynamic always uses the original triangle
11764 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11766 index = 3*e[cornerindex];
11767 VectorCopy(vertex3f + index, v[cornerindex]);
11770 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11772 // convert vertex positions to texcoords
11773 Matrix4x4_Transform(projection, v[cornerindex], temp);
11774 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11775 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11776 // calculate distance fade from the projection origin
11777 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11778 f = bound(0.0f, f, 1.0f);
11779 c[cornerindex][0] = r * f;
11780 c[cornerindex][1] = g * f;
11781 c[cornerindex][2] = b * f;
11782 c[cornerindex][3] = 1.0f;
11783 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11786 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);
11788 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11789 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);
11791 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)
11793 matrix4x4_t projection;
11794 decalsystem_t *decalsystem;
11797 const msurface_t *surface;
11798 const msurface_t *surfaces;
11799 const int *surfacelist;
11800 const texture_t *texture;
11802 int numsurfacelist;
11803 int surfacelistindex;
11806 float localorigin[3];
11807 float localnormal[3];
11808 float localmins[3];
11809 float localmaxs[3];
11812 float planes[6][4];
11815 int bih_triangles_count;
11816 int bih_triangles[256];
11817 int bih_surfaces[256];
11819 decalsystem = &ent->decalsystem;
11820 model = ent->model;
11821 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11823 R_DecalSystem_Reset(&ent->decalsystem);
11827 if (!model->brush.data_leafs && !cl_decals_models.integer)
11829 if (decalsystem->model)
11830 R_DecalSystem_Reset(decalsystem);
11834 if (decalsystem->model != model)
11835 R_DecalSystem_Reset(decalsystem);
11836 decalsystem->model = model;
11838 RSurf_ActiveModelEntity(ent, true, false, false);
11840 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11841 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11842 VectorNormalize(localnormal);
11843 localsize = worldsize*rsurface.inversematrixscale;
11844 localmins[0] = localorigin[0] - localsize;
11845 localmins[1] = localorigin[1] - localsize;
11846 localmins[2] = localorigin[2] - localsize;
11847 localmaxs[0] = localorigin[0] + localsize;
11848 localmaxs[1] = localorigin[1] + localsize;
11849 localmaxs[2] = localorigin[2] + localsize;
11851 //VectorCopy(localnormal, planes[4]);
11852 //VectorVectors(planes[4], planes[2], planes[0]);
11853 AnglesFromVectors(angles, localnormal, NULL, false);
11854 AngleVectors(angles, planes[0], planes[2], planes[4]);
11855 VectorNegate(planes[0], planes[1]);
11856 VectorNegate(planes[2], planes[3]);
11857 VectorNegate(planes[4], planes[5]);
11858 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11859 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11860 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11861 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11862 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11863 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11868 matrix4x4_t forwardprojection;
11869 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11870 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11875 float projectionvector[4][3];
11876 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11877 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11878 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11879 projectionvector[0][0] = planes[0][0] * ilocalsize;
11880 projectionvector[0][1] = planes[1][0] * ilocalsize;
11881 projectionvector[0][2] = planes[2][0] * ilocalsize;
11882 projectionvector[1][0] = planes[0][1] * ilocalsize;
11883 projectionvector[1][1] = planes[1][1] * ilocalsize;
11884 projectionvector[1][2] = planes[2][1] * ilocalsize;
11885 projectionvector[2][0] = planes[0][2] * ilocalsize;
11886 projectionvector[2][1] = planes[1][2] * ilocalsize;
11887 projectionvector[2][2] = planes[2][2] * ilocalsize;
11888 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11889 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11890 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11891 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11895 dynamic = model->surfmesh.isanimated;
11896 numsurfacelist = model->nummodelsurfaces;
11897 surfacelist = model->sortedmodelsurfaces;
11898 surfaces = model->data_surfaces;
11901 bih_triangles_count = -1;
11904 if(model->render_bih.numleafs)
11905 bih = &model->render_bih;
11906 else if(model->collision_bih.numleafs)
11907 bih = &model->collision_bih;
11910 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11911 if(bih_triangles_count == 0)
11913 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11915 if(bih_triangles_count > 0)
11917 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11919 surfaceindex = bih_surfaces[triangleindex];
11920 surface = surfaces + surfaceindex;
11921 texture = surface->texture;
11922 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11924 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11926 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11931 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11933 surfaceindex = surfacelist[surfacelistindex];
11934 surface = surfaces + surfaceindex;
11935 // check cull box first because it rejects more than any other check
11936 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11938 // skip transparent surfaces
11939 texture = surface->texture;
11940 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11942 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11944 numtriangles = surface->num_triangles;
11945 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11946 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11951 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11952 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)
11954 int renderentityindex;
11955 float worldmins[3];
11956 float worldmaxs[3];
11957 entity_render_t *ent;
11959 if (!cl_decals_newsystem.integer)
11962 worldmins[0] = worldorigin[0] - worldsize;
11963 worldmins[1] = worldorigin[1] - worldsize;
11964 worldmins[2] = worldorigin[2] - worldsize;
11965 worldmaxs[0] = worldorigin[0] + worldsize;
11966 worldmaxs[1] = worldorigin[1] + worldsize;
11967 worldmaxs[2] = worldorigin[2] + worldsize;
11969 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11971 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11973 ent = r_refdef.scene.entities[renderentityindex];
11974 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11977 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11981 typedef struct r_decalsystem_splatqueue_s
11983 vec3_t worldorigin;
11984 vec3_t worldnormal;
11990 r_decalsystem_splatqueue_t;
11992 int r_decalsystem_numqueued = 0;
11993 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11995 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)
11997 r_decalsystem_splatqueue_t *queue;
11999 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12002 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12003 VectorCopy(worldorigin, queue->worldorigin);
12004 VectorCopy(worldnormal, queue->worldnormal);
12005 Vector4Set(queue->color, r, g, b, a);
12006 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12007 queue->worldsize = worldsize;
12008 queue->decalsequence = cl.decalsequence++;
12011 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12014 r_decalsystem_splatqueue_t *queue;
12016 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12017 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);
12018 r_decalsystem_numqueued = 0;
12021 extern cvar_t cl_decals_max;
12022 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12025 decalsystem_t *decalsystem = &ent->decalsystem;
12032 if (!decalsystem->numdecals)
12035 if (r_showsurfaces.integer)
12038 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12040 R_DecalSystem_Reset(decalsystem);
12044 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12045 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12047 if (decalsystem->lastupdatetime)
12048 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12051 decalsystem->lastupdatetime = r_refdef.scene.time;
12052 numdecals = decalsystem->numdecals;
12054 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12056 if (decal->color4f[0][3])
12058 decal->lived += frametime;
12059 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12061 memset(decal, 0, sizeof(*decal));
12062 if (decalsystem->freedecal > i)
12063 decalsystem->freedecal = i;
12067 decal = decalsystem->decals;
12068 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12071 // collapse the array by shuffling the tail decals into the gaps
12074 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12075 decalsystem->freedecal++;
12076 if (decalsystem->freedecal == numdecals)
12078 decal[decalsystem->freedecal] = decal[--numdecals];
12081 decalsystem->numdecals = numdecals;
12083 if (numdecals <= 0)
12085 // if there are no decals left, reset decalsystem
12086 R_DecalSystem_Reset(decalsystem);
12090 extern skinframe_t *decalskinframe;
12091 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12094 decalsystem_t *decalsystem = &ent->decalsystem;
12103 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12106 numdecals = decalsystem->numdecals;
12110 if (r_showsurfaces.integer)
12113 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12115 R_DecalSystem_Reset(decalsystem);
12119 // if the model is static it doesn't matter what value we give for
12120 // wantnormals and wanttangents, so this logic uses only rules applicable
12121 // to a model, knowing that they are meaningless otherwise
12122 if (ent == r_refdef.scene.worldentity)
12123 RSurf_ActiveWorldEntity();
12125 RSurf_ActiveModelEntity(ent, false, false, false);
12127 decalsystem->lastupdatetime = r_refdef.scene.time;
12129 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12131 // update vertex positions for animated models
12132 v3f = decalsystem->vertex3f;
12133 c4f = decalsystem->color4f;
12134 t2f = decalsystem->texcoord2f;
12135 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12137 if (!decal->color4f[0][3])
12140 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12144 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12147 // update color values for fading decals
12148 if (decal->lived >= cl_decals_time.value)
12149 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12153 c4f[ 0] = decal->color4f[0][0] * alpha;
12154 c4f[ 1] = decal->color4f[0][1] * alpha;
12155 c4f[ 2] = decal->color4f[0][2] * alpha;
12157 c4f[ 4] = decal->color4f[1][0] * alpha;
12158 c4f[ 5] = decal->color4f[1][1] * alpha;
12159 c4f[ 6] = decal->color4f[1][2] * alpha;
12161 c4f[ 8] = decal->color4f[2][0] * alpha;
12162 c4f[ 9] = decal->color4f[2][1] * alpha;
12163 c4f[10] = decal->color4f[2][2] * alpha;
12166 t2f[0] = decal->texcoord2f[0][0];
12167 t2f[1] = decal->texcoord2f[0][1];
12168 t2f[2] = decal->texcoord2f[1][0];
12169 t2f[3] = decal->texcoord2f[1][1];
12170 t2f[4] = decal->texcoord2f[2][0];
12171 t2f[5] = decal->texcoord2f[2][1];
12173 // update vertex positions for animated models
12174 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12176 e = rsurface.modelelement3i + 3*decal->triangleindex;
12177 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12178 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12179 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12183 VectorCopy(decal->vertex3f[0], v3f);
12184 VectorCopy(decal->vertex3f[1], v3f + 3);
12185 VectorCopy(decal->vertex3f[2], v3f + 6);
12188 if (r_refdef.fogenabled)
12190 alpha = RSurf_FogVertex(v3f);
12191 VectorScale(c4f, alpha, c4f);
12192 alpha = RSurf_FogVertex(v3f + 3);
12193 VectorScale(c4f + 4, alpha, c4f + 4);
12194 alpha = RSurf_FogVertex(v3f + 6);
12195 VectorScale(c4f + 8, alpha, c4f + 8);
12206 r_refdef.stats[r_stat_drawndecals] += numtris;
12208 // now render the decals all at once
12209 // (this assumes they all use one particle font texture!)
12210 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);
12211 // R_Mesh_ResetTextureState();
12212 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12213 GL_DepthMask(false);
12214 GL_DepthRange(0, 1);
12215 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12216 GL_DepthTest(true);
12217 GL_CullFace(GL_NONE);
12218 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12219 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12220 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12224 static void R_DrawModelDecals(void)
12228 // fade faster when there are too many decals
12229 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12230 for (i = 0;i < r_refdef.scene.numentities;i++)
12231 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12233 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12234 for (i = 0;i < r_refdef.scene.numentities;i++)
12235 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12236 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12238 R_DecalSystem_ApplySplatEntitiesQueue();
12240 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12241 for (i = 0;i < r_refdef.scene.numentities;i++)
12242 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12244 r_refdef.stats[r_stat_totaldecals] += numdecals;
12246 if (r_showsurfaces.integer)
12249 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12251 for (i = 0;i < r_refdef.scene.numentities;i++)
12253 if (!r_refdef.viewcache.entityvisible[i])
12255 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12256 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12260 extern cvar_t mod_collision_bih;
12261 static void R_DrawDebugModel(void)
12263 entity_render_t *ent = rsurface.entity;
12264 int i, j, flagsmask;
12265 const msurface_t *surface;
12266 dp_model_t *model = ent->model;
12268 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12271 if (r_showoverdraw.value > 0)
12273 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12274 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12275 R_SetupShader_Generic_NoTexture(false, false);
12276 GL_DepthTest(false);
12277 GL_DepthMask(false);
12278 GL_DepthRange(0, 1);
12279 GL_BlendFunc(GL_ONE, GL_ONE);
12280 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12282 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12284 rsurface.texture = R_GetCurrentTexture(surface->texture);
12285 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12287 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12288 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12289 if (!rsurface.texture->currentlayers->depthmask)
12290 GL_Color(c, 0, 0, 1.0f);
12291 else if (ent == r_refdef.scene.worldentity)
12292 GL_Color(c, c, c, 1.0f);
12294 GL_Color(0, c, 0, 1.0f);
12295 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12299 rsurface.texture = NULL;
12302 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12304 // R_Mesh_ResetTextureState();
12305 R_SetupShader_Generic_NoTexture(false, false);
12306 GL_DepthRange(0, 1);
12307 GL_DepthTest(!r_showdisabledepthtest.integer);
12308 GL_DepthMask(false);
12309 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12311 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12315 qboolean cullbox = false;
12316 const q3mbrush_t *brush;
12317 const bih_t *bih = &model->collision_bih;
12318 const bih_leaf_t *bihleaf;
12319 float vertex3f[3][3];
12320 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12321 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12323 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12325 switch (bihleaf->type)
12328 brush = model->brush.data_brushes + bihleaf->itemindex;
12329 if (brush->colbrushf && brush->colbrushf->numtriangles)
12331 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);
12332 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12333 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12336 case BIH_COLLISIONTRIANGLE:
12337 triangleindex = bihleaf->itemindex;
12338 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12339 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12340 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12341 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);
12342 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12343 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12345 case BIH_RENDERTRIANGLE:
12346 triangleindex = bihleaf->itemindex;
12347 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12348 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12349 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12350 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);
12351 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12352 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12358 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12361 if (r_showtris.integer && qglPolygonMode)
12363 if (r_showdisabledepthtest.integer)
12365 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12366 GL_DepthMask(false);
12370 GL_BlendFunc(GL_ONE, GL_ZERO);
12371 GL_DepthMask(true);
12373 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12374 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12376 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12378 rsurface.texture = R_GetCurrentTexture(surface->texture);
12379 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12381 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12382 if (!rsurface.texture->currentlayers->depthmask)
12383 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12384 else if (ent == r_refdef.scene.worldentity)
12385 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12387 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12388 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12392 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12393 rsurface.texture = NULL;
12396 if (r_shownormals.value != 0 && qglBegin)
12400 if (r_showdisabledepthtest.integer)
12402 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12403 GL_DepthMask(false);
12407 GL_BlendFunc(GL_ONE, GL_ZERO);
12408 GL_DepthMask(true);
12410 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12412 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12414 rsurface.texture = R_GetCurrentTexture(surface->texture);
12415 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12417 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12418 qglBegin(GL_LINES);
12419 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12421 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12423 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12424 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12425 qglVertex3f(v[0], v[1], v[2]);
12426 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12427 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12428 qglVertex3f(v[0], v[1], v[2]);
12431 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12433 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12435 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12436 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12437 qglVertex3f(v[0], v[1], v[2]);
12438 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12439 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12440 qglVertex3f(v[0], v[1], v[2]);
12443 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12445 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12447 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12448 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12449 qglVertex3f(v[0], v[1], v[2]);
12450 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12451 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12452 qglVertex3f(v[0], v[1], v[2]);
12455 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12457 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12459 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12460 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12461 qglVertex3f(v[0], v[1], v[2]);
12462 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12463 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12464 qglVertex3f(v[0], v[1], v[2]);
12471 rsurface.texture = NULL;
12476 int r_maxsurfacelist = 0;
12477 const msurface_t **r_surfacelist = NULL;
12478 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12480 int i, j, endj, flagsmask;
12481 dp_model_t *model = r_refdef.scene.worldmodel;
12482 msurface_t *surfaces;
12483 unsigned char *update;
12484 int numsurfacelist = 0;
12488 if (r_maxsurfacelist < model->num_surfaces)
12490 r_maxsurfacelist = model->num_surfaces;
12492 Mem_Free((msurface_t**)r_surfacelist);
12493 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12496 RSurf_ActiveWorldEntity();
12498 surfaces = model->data_surfaces;
12499 update = model->brushq1.lightmapupdateflags;
12501 // update light styles on this submodel
12502 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12504 model_brush_lightstyleinfo_t *style;
12505 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12507 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12509 int *list = style->surfacelist;
12510 style->value = r_refdef.scene.lightstylevalue[style->style];
12511 for (j = 0;j < style->numsurfaces;j++)
12512 update[list[j]] = true;
12517 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12521 R_DrawDebugModel();
12522 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12526 rsurface.lightmaptexture = NULL;
12527 rsurface.deluxemaptexture = NULL;
12528 rsurface.uselightmaptexture = false;
12529 rsurface.texture = NULL;
12530 rsurface.rtlight = NULL;
12531 numsurfacelist = 0;
12532 // add visible surfaces to draw list
12533 for (i = 0;i < model->nummodelsurfaces;i++)
12535 j = model->sortedmodelsurfaces[i];
12536 if (r_refdef.viewcache.world_surfacevisible[j])
12537 r_surfacelist[numsurfacelist++] = surfaces + j;
12539 // update lightmaps if needed
12540 if (model->brushq1.firstrender)
12542 model->brushq1.firstrender = false;
12543 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12545 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12549 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12550 if (r_refdef.viewcache.world_surfacevisible[j])
12552 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12554 // don't do anything if there were no surfaces
12555 if (!numsurfacelist)
12557 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12560 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12562 // add to stats if desired
12563 if (r_speeds.integer && !skysurfaces && !depthonly)
12565 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12566 for (j = 0;j < numsurfacelist;j++)
12567 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12570 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12573 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12575 int i, j, endj, flagsmask;
12576 dp_model_t *model = ent->model;
12577 msurface_t *surfaces;
12578 unsigned char *update;
12579 int numsurfacelist = 0;
12583 if (r_maxsurfacelist < model->num_surfaces)
12585 r_maxsurfacelist = model->num_surfaces;
12587 Mem_Free((msurface_t **)r_surfacelist);
12588 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12591 // if the model is static it doesn't matter what value we give for
12592 // wantnormals and wanttangents, so this logic uses only rules applicable
12593 // to a model, knowing that they are meaningless otherwise
12594 if (ent == r_refdef.scene.worldentity)
12595 RSurf_ActiveWorldEntity();
12596 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12597 RSurf_ActiveModelEntity(ent, false, false, false);
12599 RSurf_ActiveModelEntity(ent, true, true, true);
12600 else if (depthonly)
12602 switch (vid.renderpath)
12604 case RENDERPATH_GL20:
12605 case RENDERPATH_D3D9:
12606 case RENDERPATH_D3D10:
12607 case RENDERPATH_D3D11:
12608 case RENDERPATH_SOFT:
12609 case RENDERPATH_GLES2:
12610 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12612 case RENDERPATH_GL11:
12613 case RENDERPATH_GL13:
12614 case RENDERPATH_GLES1:
12615 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12621 switch (vid.renderpath)
12623 case RENDERPATH_GL20:
12624 case RENDERPATH_D3D9:
12625 case RENDERPATH_D3D10:
12626 case RENDERPATH_D3D11:
12627 case RENDERPATH_SOFT:
12628 case RENDERPATH_GLES2:
12629 RSurf_ActiveModelEntity(ent, true, true, false);
12631 case RENDERPATH_GL11:
12632 case RENDERPATH_GL13:
12633 case RENDERPATH_GLES1:
12634 RSurf_ActiveModelEntity(ent, true, false, false);
12639 surfaces = model->data_surfaces;
12640 update = model->brushq1.lightmapupdateflags;
12642 // update light styles
12643 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12645 model_brush_lightstyleinfo_t *style;
12646 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12648 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12650 int *list = style->surfacelist;
12651 style->value = r_refdef.scene.lightstylevalue[style->style];
12652 for (j = 0;j < style->numsurfaces;j++)
12653 update[list[j]] = true;
12658 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12662 R_DrawDebugModel();
12663 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12667 rsurface.lightmaptexture = NULL;
12668 rsurface.deluxemaptexture = NULL;
12669 rsurface.uselightmaptexture = false;
12670 rsurface.texture = NULL;
12671 rsurface.rtlight = NULL;
12672 numsurfacelist = 0;
12673 // add visible surfaces to draw list
12674 for (i = 0;i < model->nummodelsurfaces;i++)
12675 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12676 // don't do anything if there were no surfaces
12677 if (!numsurfacelist)
12679 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12682 // update lightmaps if needed
12686 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12691 R_BuildLightMap(ent, surfaces + j);
12696 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12698 // add to stats if desired
12699 if (r_speeds.integer && !skysurfaces && !depthonly)
12701 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12702 for (j = 0;j < numsurfacelist;j++)
12703 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12706 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12709 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12711 static texture_t texture;
12712 static msurface_t surface;
12713 const msurface_t *surfacelist = &surface;
12715 // fake enough texture and surface state to render this geometry
12717 texture.update_lastrenderframe = -1; // regenerate this texture
12718 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12719 texture.currentskinframe = skinframe;
12720 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12721 texture.offsetmapping = OFFSETMAPPING_OFF;
12722 texture.offsetscale = 1;
12723 texture.specularscalemod = 1;
12724 texture.specularpowermod = 1;
12725 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12726 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12727 // JUST GREP FOR "specularscalemod = 1".
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);
12743 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)
12745 static msurface_t surface;
12746 const msurface_t *surfacelist = &surface;
12748 // fake enough texture and surface state to render this geometry
12749 surface.texture = texture;
12750 surface.num_triangles = numtriangles;
12751 surface.num_firsttriangle = firsttriangle;
12752 surface.num_vertices = numvertices;
12753 surface.num_firstvertex = firstvertex;
12756 rsurface.texture = R_GetCurrentTexture(surface.texture);
12757 rsurface.lightmaptexture = NULL;
12758 rsurface.deluxemaptexture = NULL;
12759 rsurface.uselightmaptexture = false;
12760 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);