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"},
682 {"#define USEOCCLUDE\n", " occlude"}
685 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
686 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
688 {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
689 {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690 {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691 {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692 {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693 {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694 {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
698 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
699 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
700 {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
701 {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
702 {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
703 {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
704 {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
707 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
709 {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
710 {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
711 {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
712 {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
713 {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
714 {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
715 {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
716 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
717 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
718 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
719 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
720 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
721 {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
722 {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
723 {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
724 {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
725 {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
728 struct r_glsl_permutation_s;
729 typedef struct r_glsl_permutation_s
732 struct r_glsl_permutation_s *hashnext;
734 unsigned int permutation;
736 /// indicates if we have tried compiling this permutation already
738 /// 0 if compilation failed
740 // texture units assigned to each detected uniform
741 int tex_Texture_First;
742 int tex_Texture_Second;
743 int tex_Texture_GammaRamps;
744 int tex_Texture_Normal;
745 int tex_Texture_Color;
746 int tex_Texture_Gloss;
747 int tex_Texture_Glow;
748 int tex_Texture_SecondaryNormal;
749 int tex_Texture_SecondaryColor;
750 int tex_Texture_SecondaryGloss;
751 int tex_Texture_SecondaryGlow;
752 int tex_Texture_Pants;
753 int tex_Texture_Shirt;
754 int tex_Texture_FogHeightTexture;
755 int tex_Texture_FogMask;
756 int tex_Texture_Lightmap;
757 int tex_Texture_Deluxemap;
758 int tex_Texture_Attenuation;
759 int tex_Texture_Cube;
760 int tex_Texture_Refraction;
761 int tex_Texture_Reflection;
762 int tex_Texture_ShadowMap2D;
763 int tex_Texture_CubeProjection;
764 int tex_Texture_ScreenNormalMap;
765 int tex_Texture_ScreenDiffuse;
766 int tex_Texture_ScreenSpecular;
767 int tex_Texture_ReflectMask;
768 int tex_Texture_ReflectCube;
769 int tex_Texture_BounceGrid;
770 /// locations of detected uniforms in program object, or -1 if not found
771 int loc_Texture_First;
772 int loc_Texture_Second;
773 int loc_Texture_GammaRamps;
774 int loc_Texture_Normal;
775 int loc_Texture_Color;
776 int loc_Texture_Gloss;
777 int loc_Texture_Glow;
778 int loc_Texture_SecondaryNormal;
779 int loc_Texture_SecondaryColor;
780 int loc_Texture_SecondaryGloss;
781 int loc_Texture_SecondaryGlow;
782 int loc_Texture_Pants;
783 int loc_Texture_Shirt;
784 int loc_Texture_FogHeightTexture;
785 int loc_Texture_FogMask;
786 int loc_Texture_Lightmap;
787 int loc_Texture_Deluxemap;
788 int loc_Texture_Attenuation;
789 int loc_Texture_Cube;
790 int loc_Texture_Refraction;
791 int loc_Texture_Reflection;
792 int loc_Texture_ShadowMap2D;
793 int loc_Texture_CubeProjection;
794 int loc_Texture_ScreenNormalMap;
795 int loc_Texture_ScreenDiffuse;
796 int loc_Texture_ScreenSpecular;
797 int loc_Texture_ReflectMask;
798 int loc_Texture_ReflectCube;
799 int loc_Texture_BounceGrid;
801 int loc_BloomBlur_Parameters;
803 int loc_Color_Ambient;
804 int loc_Color_Diffuse;
805 int loc_Color_Specular;
809 int loc_DeferredColor_Ambient;
810 int loc_DeferredColor_Diffuse;
811 int loc_DeferredColor_Specular;
812 int loc_DeferredMod_Diffuse;
813 int loc_DeferredMod_Specular;
814 int loc_DistortScaleRefractReflect;
817 int loc_FogHeightFade;
819 int loc_FogPlaneViewDist;
820 int loc_FogRangeRecip;
823 int loc_LightPosition;
824 int loc_OffsetMapping_ScaleSteps;
825 int loc_OffsetMapping_LodDistance;
826 int loc_OffsetMapping_Bias;
828 int loc_ReflectColor;
829 int loc_ReflectFactor;
830 int loc_ReflectOffset;
831 int loc_RefractColor;
833 int loc_ScreenCenterRefractReflect;
834 int loc_ScreenScaleRefractReflect;
835 int loc_ScreenToDepth;
836 int loc_ShadowMap_Parameters;
837 int loc_ShadowMap_TextureScale;
838 int loc_SpecularPower;
839 int loc_Skeletal_Transform12;
844 int loc_ViewTintColor;
846 int loc_ModelToLight;
848 int loc_BackgroundTexMatrix;
849 int loc_ModelViewProjectionMatrix;
850 int loc_ModelViewMatrix;
851 int loc_PixelToScreenTexCoord;
852 int loc_ModelToReflectCube;
853 int loc_ShadowMapMatrix;
854 int loc_BloomColorSubtract;
855 int loc_NormalmapScrollBlend;
856 int loc_BounceGridMatrix;
857 int loc_BounceGridIntensity;
858 /// uniform block bindings
859 int ubibind_Skeletal_Transform12_UniformBlock;
860 /// uniform block indices
861 int ubiloc_Skeletal_Transform12_UniformBlock;
863 r_glsl_permutation_t;
865 #define SHADERPERMUTATION_HASHSIZE 256
868 // non-degradable "lightweight" shader parameters to keep the permutations simpler
869 // these can NOT degrade! only use for simple stuff
872 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
873 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
874 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
875 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
876 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
877 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
878 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
879 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
880 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
881 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
882 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
883 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
884 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
885 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
887 #define SHADERSTATICPARMS_COUNT 14
889 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
890 static int shaderstaticparms_count = 0;
892 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
893 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
895 extern qboolean r_shadow_shadowmapsampler;
896 extern int r_shadow_shadowmappcf;
897 qboolean R_CompileShader_CheckStaticParms(void)
899 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
900 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
901 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
904 if (r_glsl_saturation_redcompensate.integer)
905 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
906 if (r_glsl_vertextextureblend_usebothalphas.integer)
907 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
908 if (r_shadow_glossexact.integer)
909 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
910 if (r_glsl_postprocess.integer)
912 if (r_glsl_postprocess_uservec1_enable.integer)
913 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
914 if (r_glsl_postprocess_uservec2_enable.integer)
915 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
916 if (r_glsl_postprocess_uservec3_enable.integer)
917 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
918 if (r_glsl_postprocess_uservec4_enable.integer)
919 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
922 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
923 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
924 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
926 if (r_shadow_shadowmapsampler)
927 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
928 if (r_shadow_shadowmappcf > 1)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
930 else if (r_shadow_shadowmappcf)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
932 if (r_celshading.integer)
933 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
934 if (r_celoutlines.integer)
935 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
937 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
940 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
941 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
942 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
944 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
945 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
947 shaderstaticparms_count = 0;
950 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
951 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
952 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
953 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
954 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
955 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
956 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
957 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
958 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
959 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
960 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
961 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
962 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
963 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
966 /// information about each possible shader permutation
967 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
968 /// currently selected permutation
969 r_glsl_permutation_t *r_glsl_permutation;
970 /// storage for permutations linked in the hash table
971 memexpandablearray_t r_glsl_permutationarray;
973 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
975 //unsigned int hashdepth = 0;
976 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
977 r_glsl_permutation_t *p;
978 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
980 if (p->mode == mode && p->permutation == permutation)
982 //if (hashdepth > 10)
983 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
988 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
990 p->permutation = permutation;
991 p->hashnext = r_glsl_permutationhash[mode][hashindex];
992 r_glsl_permutationhash[mode][hashindex] = p;
993 //if (hashdepth > 10)
994 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
998 static char *R_ShaderStrCat(const char **strings)
1001 const char **p = strings;
1004 for (p = strings;(t = *p);p++)
1007 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1009 for (p = strings;(t = *p);p++)
1019 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1022 if (!filename || !filename[0])
1024 // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1025 if (!strcmp(filename, "glsl/default.glsl"))
1028 return R_ShaderStrCat(builtinshaderstrings);
1029 if (!glslshaderstring)
1031 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1032 if (glslshaderstring)
1033 Con_DPrintf("Loading shaders from file %s...\n", filename);
1035 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1037 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1038 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1039 return shaderstring;
1041 if (!strcmp(filename, "hlsl/default.hlsl"))
1044 return R_ShaderStrCat(builtinhlslshaderstrings);
1045 if (!hlslshaderstring)
1047 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1048 if (hlslshaderstring)
1049 Con_DPrintf("Loading shaders from file %s...\n", filename);
1051 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1053 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1054 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1055 return shaderstring;
1057 // we don't have builtin strings for any other files
1060 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1063 if (printfromdisknotice)
1064 Con_DPrintf("from disk %s... ", filename);
1065 return shaderstring;
1067 return shaderstring;
1070 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1075 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1077 char permutationname[256];
1078 int vertstrings_count = 0;
1079 int geomstrings_count = 0;
1080 int fragstrings_count = 0;
1081 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1082 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1083 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1090 permutationname[0] = 0;
1091 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1093 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1095 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1096 if(vid.support.glshaderversion >= 140)
1098 vertstrings_list[vertstrings_count++] = "#version 140\n";
1099 geomstrings_list[geomstrings_count++] = "#version 140\n";
1100 fragstrings_list[fragstrings_count++] = "#version 140\n";
1101 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1102 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1103 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1105 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1106 else if(vid.support.glshaderversion >= 130)
1108 vertstrings_list[vertstrings_count++] = "#version 130\n";
1109 geomstrings_list[geomstrings_count++] = "#version 130\n";
1110 fragstrings_list[fragstrings_count++] = "#version 130\n";
1111 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1112 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1113 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1116 // the first pretext is which type of shader to compile as
1117 // (later these will all be bound together as a program object)
1118 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1119 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1120 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1122 // the second pretext is the mode (for example a light source)
1123 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1124 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1125 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1126 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1128 // now add all the permutation pretexts
1129 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1131 if (permutation & (1<<i))
1133 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1134 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1135 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1136 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1140 // keep line numbers correct
1141 vertstrings_list[vertstrings_count++] = "\n";
1142 geomstrings_list[geomstrings_count++] = "\n";
1143 fragstrings_list[fragstrings_count++] = "\n";
1148 R_CompileShader_AddStaticParms(mode, permutation);
1149 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1150 vertstrings_count += shaderstaticparms_count;
1151 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1152 geomstrings_count += shaderstaticparms_count;
1153 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1154 fragstrings_count += shaderstaticparms_count;
1156 // now append the shader text itself
1157 vertstrings_list[vertstrings_count++] = sourcestring;
1158 geomstrings_list[geomstrings_count++] = sourcestring;
1159 fragstrings_list[fragstrings_count++] = sourcestring;
1161 // compile the shader program
1162 if (vertstrings_count + geomstrings_count + fragstrings_count)
1163 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1167 qglUseProgram(p->program);CHECKGLERROR
1168 // look up all the uniform variable names we care about, so we don't
1169 // have to look them up every time we set them
1174 GLint activeuniformindex = 0;
1175 GLint numactiveuniforms = 0;
1176 char uniformname[128];
1177 GLsizei uniformnamelength = 0;
1178 GLint uniformsize = 0;
1179 GLenum uniformtype = 0;
1180 memset(uniformname, 0, sizeof(uniformname));
1181 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1182 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1183 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1185 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1186 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1191 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1192 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1193 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1194 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1195 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1196 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1197 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1198 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1199 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1200 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1201 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1202 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1203 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1204 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1205 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1206 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1207 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1208 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1209 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1210 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1211 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1212 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1213 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1214 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1215 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1216 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1217 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1218 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1219 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1220 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1221 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1222 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1223 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1224 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1225 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1226 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1227 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1228 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1229 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1230 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1231 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1232 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1233 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1234 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1235 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1236 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1237 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1238 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1239 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1240 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1241 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1242 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1243 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1244 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1245 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1246 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1247 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1248 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1249 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1250 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1251 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1252 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1253 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1254 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1255 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1256 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1257 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1258 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1259 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1260 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1261 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1262 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1263 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1264 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1265 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1266 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1267 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1268 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1269 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1270 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1271 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1272 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1273 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1274 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1275 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1276 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1277 // initialize the samplers to refer to the texture units we use
1278 p->tex_Texture_First = -1;
1279 p->tex_Texture_Second = -1;
1280 p->tex_Texture_GammaRamps = -1;
1281 p->tex_Texture_Normal = -1;
1282 p->tex_Texture_Color = -1;
1283 p->tex_Texture_Gloss = -1;
1284 p->tex_Texture_Glow = -1;
1285 p->tex_Texture_SecondaryNormal = -1;
1286 p->tex_Texture_SecondaryColor = -1;
1287 p->tex_Texture_SecondaryGloss = -1;
1288 p->tex_Texture_SecondaryGlow = -1;
1289 p->tex_Texture_Pants = -1;
1290 p->tex_Texture_Shirt = -1;
1291 p->tex_Texture_FogHeightTexture = -1;
1292 p->tex_Texture_FogMask = -1;
1293 p->tex_Texture_Lightmap = -1;
1294 p->tex_Texture_Deluxemap = -1;
1295 p->tex_Texture_Attenuation = -1;
1296 p->tex_Texture_Cube = -1;
1297 p->tex_Texture_Refraction = -1;
1298 p->tex_Texture_Reflection = -1;
1299 p->tex_Texture_ShadowMap2D = -1;
1300 p->tex_Texture_CubeProjection = -1;
1301 p->tex_Texture_ScreenNormalMap = -1;
1302 p->tex_Texture_ScreenDiffuse = -1;
1303 p->tex_Texture_ScreenSpecular = -1;
1304 p->tex_Texture_ReflectMask = -1;
1305 p->tex_Texture_ReflectCube = -1;
1306 p->tex_Texture_BounceGrid = -1;
1307 // bind the texture samplers in use
1309 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1310 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1311 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1312 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1313 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1314 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1315 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1316 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1317 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1318 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1319 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1320 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1321 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1322 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1323 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1324 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1325 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1326 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1327 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1328 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1329 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1330 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1331 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1332 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1333 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1334 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1335 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1336 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1337 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1338 // get the uniform block indices so we can bind them
1339 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1340 if (vid.support.arb_uniform_buffer_object)
1341 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1344 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1345 // clear the uniform block bindings
1346 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1347 // bind the uniform blocks in use
1349 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1350 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1352 // we're done compiling and setting up the shader, at least until it is used
1354 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1357 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1361 Mem_Free(sourcestring);
1364 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1366 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1367 if (r_glsl_permutation != perm)
1369 r_glsl_permutation = perm;
1370 if (!r_glsl_permutation->program)
1372 if (!r_glsl_permutation->compiled)
1374 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1375 R_GLSL_CompilePermutation(perm, mode, permutation);
1377 if (!r_glsl_permutation->program)
1379 // remove features until we find a valid permutation
1381 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1383 // reduce i more quickly whenever it would not remove any bits
1384 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1385 if (!(permutation & j))
1388 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1389 if (!r_glsl_permutation->compiled)
1390 R_GLSL_CompilePermutation(perm, mode, permutation);
1391 if (r_glsl_permutation->program)
1394 if (i >= SHADERPERMUTATION_COUNT)
1396 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1397 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1398 qglUseProgram(0);CHECKGLERROR
1399 return; // no bit left to clear, entire mode is broken
1404 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1406 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1407 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1408 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1416 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1417 extern D3DCAPS9 vid_d3d9caps;
1420 struct r_hlsl_permutation_s;
1421 typedef struct r_hlsl_permutation_s
1423 /// hash lookup data
1424 struct r_hlsl_permutation_s *hashnext;
1426 unsigned int permutation;
1428 /// indicates if we have tried compiling this permutation already
1430 /// NULL if compilation failed
1431 IDirect3DVertexShader9 *vertexshader;
1432 IDirect3DPixelShader9 *pixelshader;
1434 r_hlsl_permutation_t;
1436 typedef enum D3DVSREGISTER_e
1438 D3DVSREGISTER_TexMatrix = 0, // float4x4
1439 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1440 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1441 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1442 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1443 D3DVSREGISTER_ModelToLight = 20, // float4x4
1444 D3DVSREGISTER_EyePosition = 24,
1445 D3DVSREGISTER_FogPlane = 25,
1446 D3DVSREGISTER_LightDir = 26,
1447 D3DVSREGISTER_LightPosition = 27,
1451 typedef enum D3DPSREGISTER_e
1453 D3DPSREGISTER_Alpha = 0,
1454 D3DPSREGISTER_BloomBlur_Parameters = 1,
1455 D3DPSREGISTER_ClientTime = 2,
1456 D3DPSREGISTER_Color_Ambient = 3,
1457 D3DPSREGISTER_Color_Diffuse = 4,
1458 D3DPSREGISTER_Color_Specular = 5,
1459 D3DPSREGISTER_Color_Glow = 6,
1460 D3DPSREGISTER_Color_Pants = 7,
1461 D3DPSREGISTER_Color_Shirt = 8,
1462 D3DPSREGISTER_DeferredColor_Ambient = 9,
1463 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1464 D3DPSREGISTER_DeferredColor_Specular = 11,
1465 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1466 D3DPSREGISTER_DeferredMod_Specular = 13,
1467 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1468 D3DPSREGISTER_EyePosition = 15, // unused
1469 D3DPSREGISTER_FogColor = 16,
1470 D3DPSREGISTER_FogHeightFade = 17,
1471 D3DPSREGISTER_FogPlane = 18,
1472 D3DPSREGISTER_FogPlaneViewDist = 19,
1473 D3DPSREGISTER_FogRangeRecip = 20,
1474 D3DPSREGISTER_LightColor = 21,
1475 D3DPSREGISTER_LightDir = 22, // unused
1476 D3DPSREGISTER_LightPosition = 23,
1477 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1478 D3DPSREGISTER_PixelSize = 25,
1479 D3DPSREGISTER_ReflectColor = 26,
1480 D3DPSREGISTER_ReflectFactor = 27,
1481 D3DPSREGISTER_ReflectOffset = 28,
1482 D3DPSREGISTER_RefractColor = 29,
1483 D3DPSREGISTER_Saturation = 30,
1484 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1485 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1486 D3DPSREGISTER_ScreenToDepth = 33,
1487 D3DPSREGISTER_ShadowMap_Parameters = 34,
1488 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1489 D3DPSREGISTER_SpecularPower = 36,
1490 D3DPSREGISTER_UserVec1 = 37,
1491 D3DPSREGISTER_UserVec2 = 38,
1492 D3DPSREGISTER_UserVec3 = 39,
1493 D3DPSREGISTER_UserVec4 = 40,
1494 D3DPSREGISTER_ViewTintColor = 41,
1495 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1496 D3DPSREGISTER_BloomColorSubtract = 43,
1497 D3DPSREGISTER_ViewToLight = 44, // float4x4
1498 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1499 D3DPSREGISTER_NormalmapScrollBlend = 52,
1500 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1501 D3DPSREGISTER_OffsetMapping_Bias = 54,
1506 /// information about each possible shader permutation
1507 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1508 /// currently selected permutation
1509 r_hlsl_permutation_t *r_hlsl_permutation;
1510 /// storage for permutations linked in the hash table
1511 memexpandablearray_t r_hlsl_permutationarray;
1513 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1515 //unsigned int hashdepth = 0;
1516 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1517 r_hlsl_permutation_t *p;
1518 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1520 if (p->mode == mode && p->permutation == permutation)
1522 //if (hashdepth > 10)
1523 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1528 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1530 p->permutation = permutation;
1531 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1532 r_hlsl_permutationhash[mode][hashindex] = p;
1533 //if (hashdepth > 10)
1534 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1539 //#include <d3dx9shader.h>
1540 //#include <d3dx9mesh.h>
1542 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1544 DWORD *vsbin = NULL;
1545 DWORD *psbin = NULL;
1546 fs_offset_t vsbinsize;
1547 fs_offset_t psbinsize;
1548 // IDirect3DVertexShader9 *vs = NULL;
1549 // IDirect3DPixelShader9 *ps = NULL;
1550 ID3DXBuffer *vslog = NULL;
1551 ID3DXBuffer *vsbuffer = NULL;
1552 ID3DXConstantTable *vsconstanttable = NULL;
1553 ID3DXBuffer *pslog = NULL;
1554 ID3DXBuffer *psbuffer = NULL;
1555 ID3DXConstantTable *psconstanttable = NULL;
1558 char temp[MAX_INPUTLINE];
1559 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1561 qboolean debugshader = gl_paranoid.integer != 0;
1562 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1563 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1566 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1567 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1569 if ((!vsbin && vertstring) || (!psbin && fragstring))
1571 const char* dllnames_d3dx9 [] =
1595 dllhandle_t d3dx9_dll = NULL;
1596 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1597 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1598 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1599 dllfunction_t d3dx9_dllfuncs[] =
1601 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1602 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1603 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1606 // 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...
1607 #ifndef ID3DXBuffer_GetBufferPointer
1608 #if !defined(__cplusplus) || defined(CINTERFACE)
1609 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1610 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1611 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1613 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1614 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1615 #define ID3DXBuffer_Release(p) (p)->Release()
1618 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1620 DWORD shaderflags = 0;
1622 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1623 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1624 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1625 if (vertstring && vertstring[0])
1629 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1630 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1633 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1636 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1637 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1638 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1639 ID3DXBuffer_Release(vsbuffer);
1643 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1644 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1645 ID3DXBuffer_Release(vslog);
1648 if (fragstring && fragstring[0])
1652 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1653 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1656 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1659 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1660 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1661 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1662 ID3DXBuffer_Release(psbuffer);
1666 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1667 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1668 ID3DXBuffer_Release(pslog);
1671 Sys_UnloadLibrary(&d3dx9_dll);
1674 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1678 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1679 if (FAILED(vsresult))
1680 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1681 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1682 if (FAILED(psresult))
1683 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1685 // free the shader data
1686 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1687 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1690 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1693 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1694 int vertstring_length = 0;
1695 int geomstring_length = 0;
1696 int fragstring_length = 0;
1699 char *vertstring, *geomstring, *fragstring;
1700 char permutationname[256];
1701 char cachename[256];
1702 int vertstrings_count = 0;
1703 int geomstrings_count = 0;
1704 int fragstrings_count = 0;
1705 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1706 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1707 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1712 p->vertexshader = NULL;
1713 p->pixelshader = NULL;
1715 permutationname[0] = 0;
1717 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1719 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1720 strlcat(cachename, "hlsl/", sizeof(cachename));
1722 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1723 vertstrings_count = 0;
1724 geomstrings_count = 0;
1725 fragstrings_count = 0;
1726 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1727 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1728 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1730 // the first pretext is which type of shader to compile as
1731 // (later these will all be bound together as a program object)
1732 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1733 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1734 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1736 // the second pretext is the mode (for example a light source)
1737 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1738 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1739 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1740 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1741 strlcat(cachename, modeinfo->name, sizeof(cachename));
1743 // now add all the permutation pretexts
1744 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1746 if (permutation & (1<<i))
1748 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1749 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1750 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1751 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1752 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1756 // keep line numbers correct
1757 vertstrings_list[vertstrings_count++] = "\n";
1758 geomstrings_list[geomstrings_count++] = "\n";
1759 fragstrings_list[fragstrings_count++] = "\n";
1764 R_CompileShader_AddStaticParms(mode, permutation);
1765 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1766 vertstrings_count += shaderstaticparms_count;
1767 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1768 geomstrings_count += shaderstaticparms_count;
1769 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1770 fragstrings_count += shaderstaticparms_count;
1772 // replace spaces in the cachename with _ characters
1773 for (i = 0;cachename[i];i++)
1774 if (cachename[i] == ' ')
1777 // now append the shader text itself
1778 vertstrings_list[vertstrings_count++] = sourcestring;
1779 geomstrings_list[geomstrings_count++] = sourcestring;
1780 fragstrings_list[fragstrings_count++] = sourcestring;
1782 vertstring_length = 0;
1783 for (i = 0;i < vertstrings_count;i++)
1784 vertstring_length += (int)strlen(vertstrings_list[i]);
1785 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1786 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1787 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1789 geomstring_length = 0;
1790 for (i = 0;i < geomstrings_count;i++)
1791 geomstring_length += (int)strlen(geomstrings_list[i]);
1792 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1793 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1794 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1796 fragstring_length = 0;
1797 for (i = 0;i < fragstrings_count;i++)
1798 fragstring_length += (int)strlen(fragstrings_list[i]);
1799 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1800 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1801 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1803 // try to load the cached shader, or generate one
1804 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1806 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1807 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1809 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1813 Mem_Free(vertstring);
1815 Mem_Free(geomstring);
1817 Mem_Free(fragstring);
1819 Mem_Free(sourcestring);
1822 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1823 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1824 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);}
1825 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);}
1826 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);}
1827 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);}
1829 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1830 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1831 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);}
1832 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);}
1833 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);}
1834 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);}
1836 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1838 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1839 if (r_hlsl_permutation != perm)
1841 r_hlsl_permutation = perm;
1842 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1844 if (!r_hlsl_permutation->compiled)
1845 R_HLSL_CompilePermutation(perm, mode, permutation);
1846 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1848 // remove features until we find a valid permutation
1850 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1852 // reduce i more quickly whenever it would not remove any bits
1853 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1854 if (!(permutation & j))
1857 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1858 if (!r_hlsl_permutation->compiled)
1859 R_HLSL_CompilePermutation(perm, mode, permutation);
1860 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1863 if (i >= SHADERPERMUTATION_COUNT)
1865 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1866 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1867 return; // no bit left to clear, entire mode is broken
1871 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1872 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1874 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1875 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1876 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1880 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1882 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1883 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1884 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1885 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1888 void R_GLSL_Restart_f(void)
1890 unsigned int i, limit;
1891 if (glslshaderstring)
1892 Mem_Free(glslshaderstring);
1893 glslshaderstring = NULL;
1894 if (hlslshaderstring)
1895 Mem_Free(hlslshaderstring);
1896 hlslshaderstring = NULL;
1897 switch(vid.renderpath)
1899 case RENDERPATH_D3D9:
1902 r_hlsl_permutation_t *p;
1903 r_hlsl_permutation = NULL;
1904 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1905 for (i = 0;i < limit;i++)
1907 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1909 if (p->vertexshader)
1910 IDirect3DVertexShader9_Release(p->vertexshader);
1912 IDirect3DPixelShader9_Release(p->pixelshader);
1913 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1916 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1920 case RENDERPATH_D3D10:
1921 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1923 case RENDERPATH_D3D11:
1924 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1926 case RENDERPATH_GL20:
1927 case RENDERPATH_GLES2:
1929 r_glsl_permutation_t *p;
1930 r_glsl_permutation = NULL;
1931 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1932 for (i = 0;i < limit;i++)
1934 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1936 GL_Backend_FreeProgram(p->program);
1937 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1940 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1943 case RENDERPATH_GL11:
1944 case RENDERPATH_GL13:
1945 case RENDERPATH_GLES1:
1947 case RENDERPATH_SOFT:
1952 static void R_GLSL_DumpShader_f(void)
1954 int i, language, mode, dupe;
1956 shadermodeinfo_t *modeinfo;
1959 for (language = 0;language < 2;language++)
1961 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1962 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1964 // don't dump the same file multiple times (most or all shaders come from the same file)
1965 for (dupe = mode - 1;dupe >= 0;dupe--)
1966 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1970 text = R_GetShaderText(modeinfo[mode].filename, false, true);
1973 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1976 FS_Print(file, "/* The engine may define the following macros:\n");
1977 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1978 for (i = 0;i < SHADERMODE_COUNT;i++)
1979 FS_Print(file, modeinfo[i].pretext);
1980 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1981 FS_Print(file, shaderpermutationinfo[i].pretext);
1982 FS_Print(file, "*/\n");
1983 FS_Print(file, text);
1985 Con_Printf("%s written\n", modeinfo[mode].filename);
1988 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1994 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1996 unsigned int permutation = 0;
1997 if (r_trippy.integer && !notrippy)
1998 permutation |= SHADERPERMUTATION_TRIPPY;
1999 permutation |= SHADERPERMUTATION_VIEWTINT;
2001 permutation |= SHADERPERMUTATION_DIFFUSE;
2003 permutation |= SHADERPERMUTATION_SPECULAR;
2004 if (texturemode == GL_MODULATE)
2005 permutation |= SHADERPERMUTATION_COLORMAPPING;
2006 else if (texturemode == GL_ADD)
2007 permutation |= SHADERPERMUTATION_GLOW;
2008 else if (texturemode == GL_DECAL)
2009 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2010 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2011 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2012 if (suppresstexalpha)
2013 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2015 texturemode = GL_MODULATE;
2016 if (vid.allowalphatocoverage)
2017 GL_AlphaToCoverage(false);
2018 switch (vid.renderpath)
2020 case RENDERPATH_D3D9:
2022 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2023 R_Mesh_TexBind(GL20TU_FIRST , first );
2024 R_Mesh_TexBind(GL20TU_SECOND, second);
2025 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2026 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2029 case RENDERPATH_D3D10:
2030 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2032 case RENDERPATH_D3D11:
2033 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2035 case RENDERPATH_GL20:
2036 case RENDERPATH_GLES2:
2037 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2038 if (r_glsl_permutation->tex_Texture_First >= 0)
2039 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2040 if (r_glsl_permutation->tex_Texture_Second >= 0)
2041 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2042 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2043 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2045 case RENDERPATH_GL13:
2046 case RENDERPATH_GLES1:
2047 R_Mesh_TexBind(0, first );
2048 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2049 R_Mesh_TexMatrix(0, NULL);
2050 R_Mesh_TexBind(1, second);
2053 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2054 R_Mesh_TexMatrix(1, NULL);
2057 case RENDERPATH_GL11:
2058 R_Mesh_TexBind(0, first );
2059 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2060 R_Mesh_TexMatrix(0, NULL);
2062 case RENDERPATH_SOFT:
2063 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2064 R_Mesh_TexBind(GL20TU_FIRST , first );
2065 R_Mesh_TexBind(GL20TU_SECOND, second);
2070 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2072 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2075 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2077 unsigned int permutation = 0;
2078 if (r_trippy.integer && !notrippy)
2079 permutation |= SHADERPERMUTATION_TRIPPY;
2081 permutation |= SHADERPERMUTATION_DEPTHRGB;
2083 permutation |= SHADERPERMUTATION_SKELETAL;
2085 if (vid.allowalphatocoverage)
2086 GL_AlphaToCoverage(false);
2087 switch (vid.renderpath)
2089 case RENDERPATH_D3D9:
2091 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2094 case RENDERPATH_D3D10:
2095 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2097 case RENDERPATH_D3D11:
2098 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2100 case RENDERPATH_GL20:
2101 case RENDERPATH_GLES2:
2102 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2103 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2104 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);
2107 case RENDERPATH_GL13:
2108 case RENDERPATH_GLES1:
2109 R_Mesh_TexBind(0, 0);
2110 R_Mesh_TexBind(1, 0);
2112 case RENDERPATH_GL11:
2113 R_Mesh_TexBind(0, 0);
2115 case RENDERPATH_SOFT:
2116 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2121 extern qboolean r_shadow_usingdeferredprepass;
2122 extern rtexture_t *r_shadow_attenuationgradienttexture;
2123 extern rtexture_t *r_shadow_attenuation2dtexture;
2124 extern rtexture_t *r_shadow_attenuation3dtexture;
2125 extern qboolean r_shadow_usingshadowmap2d;
2126 extern qboolean r_shadow_usingshadowmaportho;
2127 extern float r_shadow_shadowmap_texturescale[2];
2128 extern float r_shadow_shadowmap_parameters[4];
2129 extern qboolean r_shadow_shadowmapvsdct;
2130 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2131 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2132 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2133 extern matrix4x4_t r_shadow_shadowmapmatrix;
2134 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2135 extern int r_shadow_prepass_width;
2136 extern int r_shadow_prepass_height;
2137 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2138 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2139 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2140 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2142 #define BLENDFUNC_ALLOWS_COLORMOD 1
2143 #define BLENDFUNC_ALLOWS_FOG 2
2144 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2145 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2146 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2147 static int R_BlendFuncFlags(int src, int dst)
2151 // a blendfunc allows colormod if:
2152 // a) it can never keep the destination pixel invariant, or
2153 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2154 // this is to prevent unintended side effects from colormod
2156 // a blendfunc allows fog if:
2157 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2158 // this is to prevent unintended side effects from fog
2160 // these checks are the output of fogeval.pl
2162 r |= BLENDFUNC_ALLOWS_COLORMOD;
2163 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2164 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2165 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2166 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2167 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2168 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2169 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2170 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2171 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2172 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2173 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2174 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2175 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2176 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2177 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2178 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2181 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2182 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2183 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2188 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)
2190 // select a permutation of the lighting shader appropriate to this
2191 // combination of texture, entity, light source, and fogging, only use the
2192 // minimum features necessary to avoid wasting rendering time in the
2193 // fragment shader on features that are not being used
2194 unsigned int permutation = 0;
2195 unsigned int mode = 0;
2197 static float dummy_colormod[3] = {1, 1, 1};
2198 float *colormod = rsurface.colormod;
2200 matrix4x4_t tempmatrix;
2201 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2202 if (r_trippy.integer && !notrippy)
2203 permutation |= SHADERPERMUTATION_TRIPPY;
2204 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2205 permutation |= SHADERPERMUTATION_ALPHAKILL;
2206 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2207 permutation |= SHADERPERMUTATION_OCCLUDE;
2208 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2209 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2210 if (rsurfacepass == RSURFPASS_BACKGROUND)
2212 // distorted background
2213 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2215 mode = SHADERMODE_WATER;
2216 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2217 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2218 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2220 // this is the right thing to do for wateralpha
2221 GL_BlendFunc(GL_ONE, GL_ZERO);
2222 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2226 // this is the right thing to do for entity alpha
2227 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2228 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2231 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2233 mode = SHADERMODE_REFRACTION;
2234 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2235 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2236 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2237 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241 mode = SHADERMODE_GENERIC;
2242 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2243 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2244 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2246 if (vid.allowalphatocoverage)
2247 GL_AlphaToCoverage(false);
2249 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2251 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2253 switch(rsurface.texture->offsetmapping)
2255 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2256 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2258 case OFFSETMAPPING_OFF: break;
2261 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2262 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2263 // normalmap (deferred prepass), may use alpha test on diffuse
2264 mode = SHADERMODE_DEFERREDGEOMETRY;
2265 GL_BlendFunc(GL_ONE, GL_ZERO);
2266 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2267 if (vid.allowalphatocoverage)
2268 GL_AlphaToCoverage(false);
2270 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2272 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2274 switch(rsurface.texture->offsetmapping)
2276 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2277 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2278 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2279 case OFFSETMAPPING_OFF: break;
2282 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2283 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2284 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2285 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2287 mode = SHADERMODE_LIGHTSOURCE;
2288 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2289 permutation |= SHADERPERMUTATION_CUBEFILTER;
2290 if (diffusescale > 0)
2291 permutation |= SHADERPERMUTATION_DIFFUSE;
2292 if (specularscale > 0)
2293 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2294 if (r_refdef.fogenabled)
2295 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2296 if (rsurface.texture->colormapping)
2297 permutation |= SHADERPERMUTATION_COLORMAPPING;
2298 if (r_shadow_usingshadowmap2d)
2300 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2301 if(r_shadow_shadowmapvsdct)
2302 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2304 if (r_shadow_shadowmap2ddepthbuffer)
2305 permutation |= SHADERPERMUTATION_DEPTHRGB;
2307 if (rsurface.texture->reflectmasktexture)
2308 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2309 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2310 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2311 if (vid.allowalphatocoverage)
2312 GL_AlphaToCoverage(false);
2314 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2316 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2318 switch(rsurface.texture->offsetmapping)
2320 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2321 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2322 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2323 case OFFSETMAPPING_OFF: break;
2326 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2327 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2328 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2329 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2330 // unshaded geometry (fullbright or ambient model lighting)
2331 mode = SHADERMODE_FLATCOLOR;
2332 ambientscale = diffusescale = specularscale = 0;
2333 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2334 permutation |= SHADERPERMUTATION_GLOW;
2335 if (r_refdef.fogenabled)
2336 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2337 if (rsurface.texture->colormapping)
2338 permutation |= SHADERPERMUTATION_COLORMAPPING;
2339 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2341 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2342 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2344 if (r_shadow_shadowmap2ddepthbuffer)
2345 permutation |= SHADERPERMUTATION_DEPTHRGB;
2347 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2348 permutation |= SHADERPERMUTATION_REFLECTION;
2349 if (rsurface.texture->reflectmasktexture)
2350 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2351 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353 // when using alphatocoverage, we don't need alphakill
2354 if (vid.allowalphatocoverage)
2356 if (r_transparent_alphatocoverage.integer)
2358 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2359 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2362 GL_AlphaToCoverage(false);
2365 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2367 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2369 switch(rsurface.texture->offsetmapping)
2371 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2372 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2373 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2374 case OFFSETMAPPING_OFF: break;
2377 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2378 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2379 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2380 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2381 // directional model lighting
2382 mode = SHADERMODE_LIGHTDIRECTION;
2383 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2384 permutation |= SHADERPERMUTATION_GLOW;
2385 permutation |= SHADERPERMUTATION_DIFFUSE;
2386 if (specularscale > 0)
2387 permutation |= SHADERPERMUTATION_SPECULAR;
2388 if (r_refdef.fogenabled)
2389 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2390 if (rsurface.texture->colormapping)
2391 permutation |= SHADERPERMUTATION_COLORMAPPING;
2392 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2394 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2395 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2397 if (r_shadow_shadowmap2ddepthbuffer)
2398 permutation |= SHADERPERMUTATION_DEPTHRGB;
2400 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2401 permutation |= SHADERPERMUTATION_REFLECTION;
2402 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2403 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2404 if (rsurface.texture->reflectmasktexture)
2405 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2406 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2408 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2409 if (r_shadow_bouncegriddirectional)
2410 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2412 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414 // when using alphatocoverage, we don't need alphakill
2415 if (vid.allowalphatocoverage)
2417 if (r_transparent_alphatocoverage.integer)
2419 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2420 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2423 GL_AlphaToCoverage(false);
2426 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2428 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2430 switch(rsurface.texture->offsetmapping)
2432 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2433 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2434 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2435 case OFFSETMAPPING_OFF: break;
2438 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2439 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2440 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2441 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2442 // ambient model lighting
2443 mode = SHADERMODE_LIGHTDIRECTION;
2444 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2445 permutation |= SHADERPERMUTATION_GLOW;
2446 if (r_refdef.fogenabled)
2447 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2448 if (rsurface.texture->colormapping)
2449 permutation |= SHADERPERMUTATION_COLORMAPPING;
2450 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2452 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2453 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2455 if (r_shadow_shadowmap2ddepthbuffer)
2456 permutation |= SHADERPERMUTATION_DEPTHRGB;
2458 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2459 permutation |= SHADERPERMUTATION_REFLECTION;
2460 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2461 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2462 if (rsurface.texture->reflectmasktexture)
2463 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2464 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2466 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2467 if (r_shadow_bouncegriddirectional)
2468 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2470 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2471 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2472 // when using alphatocoverage, we don't need alphakill
2473 if (vid.allowalphatocoverage)
2475 if (r_transparent_alphatocoverage.integer)
2477 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2478 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2481 GL_AlphaToCoverage(false);
2486 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2488 switch(rsurface.texture->offsetmapping)
2490 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2491 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2492 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2493 case OFFSETMAPPING_OFF: break;
2496 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2497 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2498 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2499 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2501 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2502 permutation |= SHADERPERMUTATION_GLOW;
2503 if (r_refdef.fogenabled)
2504 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2505 if (rsurface.texture->colormapping)
2506 permutation |= SHADERPERMUTATION_COLORMAPPING;
2507 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2509 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2510 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2512 if (r_shadow_shadowmap2ddepthbuffer)
2513 permutation |= SHADERPERMUTATION_DEPTHRGB;
2515 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2516 permutation |= SHADERPERMUTATION_REFLECTION;
2517 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2518 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2519 if (rsurface.texture->reflectmasktexture)
2520 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2521 if (FAKELIGHT_ENABLED)
2523 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2524 mode = SHADERMODE_FAKELIGHT;
2525 permutation |= SHADERPERMUTATION_DIFFUSE;
2526 if (specularscale > 0)
2527 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2529 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2531 // deluxemapping (light direction texture)
2532 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2533 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2535 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2536 permutation |= SHADERPERMUTATION_DIFFUSE;
2537 if (specularscale > 0)
2538 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2540 else if (r_glsl_deluxemapping.integer >= 2)
2542 // fake deluxemapping (uniform light direction in tangentspace)
2543 if (rsurface.uselightmaptexture)
2544 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2546 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2547 permutation |= SHADERPERMUTATION_DIFFUSE;
2548 if (specularscale > 0)
2549 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2551 else if (rsurface.uselightmaptexture)
2553 // ordinary lightmapping (q1bsp, q3bsp)
2554 mode = SHADERMODE_LIGHTMAP;
2558 // ordinary vertex coloring (q3bsp)
2559 mode = SHADERMODE_VERTEXCOLOR;
2561 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2563 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2564 if (r_shadow_bouncegriddirectional)
2565 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2567 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2568 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2569 // when using alphatocoverage, we don't need alphakill
2570 if (vid.allowalphatocoverage)
2572 if (r_transparent_alphatocoverage.integer)
2574 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2575 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2578 GL_AlphaToCoverage(false);
2581 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2582 colormod = dummy_colormod;
2583 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2584 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2585 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2586 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2587 switch(vid.renderpath)
2589 case RENDERPATH_D3D9:
2591 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);
2592 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2593 R_SetupShader_SetPermutationHLSL(mode, permutation);
2594 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2595 if (mode == SHADERMODE_LIGHTSOURCE)
2597 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2598 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2602 if (mode == SHADERMODE_LIGHTDIRECTION)
2604 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2607 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2608 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2609 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2610 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2611 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2613 if (mode == SHADERMODE_LIGHTSOURCE)
2615 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2616 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2617 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2618 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2619 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2621 // additive passes are only darkened by fog, not tinted
2622 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2623 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2627 if (mode == SHADERMODE_FLATCOLOR)
2629 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2631 else if (mode == SHADERMODE_LIGHTDIRECTION)
2633 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]);
2634 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2635 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);
2636 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2637 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2638 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2639 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2643 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2644 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2645 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);
2646 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2647 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2649 // additive passes are only darkened by fog, not tinted
2650 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2651 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2653 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2654 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);
2655 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2656 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2657 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2658 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2659 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2660 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2661 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2662 if (mode == SHADERMODE_WATER)
2663 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2665 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2666 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2667 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2668 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));
2669 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2670 if (rsurface.texture->pantstexture)
2671 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2673 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2674 if (rsurface.texture->shirttexture)
2675 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2677 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2678 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2679 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2680 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2681 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2682 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2683 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2684 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2685 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2688 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2689 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2690 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2691 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2693 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2694 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2695 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2696 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2697 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2698 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2699 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2700 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2701 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2702 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2703 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2704 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2705 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2706 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2707 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2708 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2709 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2710 if (rsurfacepass == RSURFPASS_BACKGROUND)
2712 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2713 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2714 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2718 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2720 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2721 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2722 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2723 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2725 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2726 if (rsurface.rtlight)
2728 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2729 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2734 case RENDERPATH_D3D10:
2735 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2737 case RENDERPATH_D3D11:
2738 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2740 case RENDERPATH_GL20:
2741 case RENDERPATH_GLES2:
2742 if (!vid.useinterleavedarrays)
2744 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);
2745 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2746 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2747 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2748 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2749 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2750 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2751 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2752 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2753 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2754 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2758 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);
2759 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2761 // this has to be after RSurf_PrepareVerticesForBatch
2762 if (rsurface.batchskeletaltransform3x4buffer)
2763 permutation |= SHADERPERMUTATION_SKELETAL;
2764 R_SetupShader_SetPermutationGLSL(mode, permutation);
2765 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2766 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);
2768 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2769 if (mode == SHADERMODE_LIGHTSOURCE)
2771 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2772 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2773 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2774 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2775 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2776 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);
2778 // additive passes are only darkened by fog, not tinted
2779 if (r_glsl_permutation->loc_FogColor >= 0)
2780 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2781 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2785 if (mode == SHADERMODE_FLATCOLOR)
2787 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2789 else if (mode == SHADERMODE_LIGHTDIRECTION)
2791 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]);
2792 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]);
2793 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);
2794 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2795 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2796 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]);
2797 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]);
2801 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]);
2802 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]);
2803 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);
2804 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2805 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2807 // additive passes are only darkened by fog, not tinted
2808 if (r_glsl_permutation->loc_FogColor >= 0)
2810 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2811 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2813 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2815 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);
2816 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]);
2817 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]);
2818 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]);
2819 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]);
2820 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2821 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2822 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);
2823 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]);
2825 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2826 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2827 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2828 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]);
2829 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]);
2831 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2832 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));
2833 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2834 if (r_glsl_permutation->loc_Color_Pants >= 0)
2836 if (rsurface.texture->pantstexture)
2837 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2839 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2841 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2843 if (rsurface.texture->shirttexture)
2844 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2846 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2848 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]);
2849 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2850 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2851 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2852 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2853 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2854 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2855 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2856 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2858 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);
2859 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2860 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]);
2861 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2862 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);}
2863 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2865 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2866 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2867 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2868 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2869 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2870 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2871 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2872 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2873 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2874 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2875 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2876 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2877 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2878 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2879 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);
2880 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2881 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2882 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2883 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2884 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2885 if (rsurfacepass == RSURFPASS_BACKGROUND)
2887 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);
2888 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);
2889 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);
2893 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);
2895 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2896 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2897 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2898 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2900 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2901 if (rsurface.rtlight)
2903 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2904 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2907 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2910 case RENDERPATH_GL11:
2911 case RENDERPATH_GL13:
2912 case RENDERPATH_GLES1:
2914 case RENDERPATH_SOFT:
2915 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);
2916 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2917 R_SetupShader_SetPermutationSoft(mode, permutation);
2918 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2919 if (mode == SHADERMODE_LIGHTSOURCE)
2921 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2922 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2923 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2924 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2925 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2926 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2928 // additive passes are only darkened by fog, not tinted
2929 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2930 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2934 if (mode == SHADERMODE_FLATCOLOR)
2936 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2938 else if (mode == SHADERMODE_LIGHTDIRECTION)
2940 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]);
2941 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2942 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);
2943 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2944 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2945 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]);
2946 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2950 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2951 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2952 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);
2953 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2954 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2956 // additive passes are only darkened by fog, not tinted
2957 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2958 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2960 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2961 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);
2962 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]);
2963 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]);
2964 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]);
2965 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]);
2966 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2967 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2968 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2969 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2971 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2972 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2973 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2974 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2975 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]);
2977 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2978 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));
2979 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2980 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2982 if (rsurface.texture->pantstexture)
2983 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2985 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2987 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2989 if (rsurface.texture->shirttexture)
2990 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2992 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2994 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2995 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2996 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2997 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2998 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2999 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3000 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3001 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3002 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3004 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3005 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3006 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3007 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3009 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3010 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3011 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3012 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3013 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3014 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3015 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3016 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3017 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3018 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3019 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3020 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3021 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3022 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3023 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3024 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3025 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3026 if (rsurfacepass == RSURFPASS_BACKGROUND)
3028 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3029 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3030 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3034 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3036 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3037 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3038 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3039 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3041 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3042 if (rsurface.rtlight)
3044 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3045 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3052 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3054 // select a permutation of the lighting shader appropriate to this
3055 // combination of texture, entity, light source, and fogging, only use the
3056 // minimum features necessary to avoid wasting rendering time in the
3057 // fragment shader on features that are not being used
3058 unsigned int permutation = 0;
3059 unsigned int mode = 0;
3060 const float *lightcolorbase = rtlight->currentcolor;
3061 float ambientscale = rtlight->ambientscale;
3062 float diffusescale = rtlight->diffusescale;
3063 float specularscale = rtlight->specularscale;
3064 // this is the location of the light in view space
3065 vec3_t viewlightorigin;
3066 // this transforms from view space (camera) to light space (cubemap)
3067 matrix4x4_t viewtolight;
3068 matrix4x4_t lighttoview;
3069 float viewtolight16f[16];
3071 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3072 if (rtlight->currentcubemap != r_texture_whitecube)
3073 permutation |= SHADERPERMUTATION_CUBEFILTER;
3074 if (diffusescale > 0)
3075 permutation |= SHADERPERMUTATION_DIFFUSE;
3076 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3077 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3078 if (r_shadow_usingshadowmap2d)
3080 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3081 if (r_shadow_shadowmapvsdct)
3082 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3084 if (r_shadow_shadowmap2ddepthbuffer)
3085 permutation |= SHADERPERMUTATION_DEPTHRGB;
3087 if (vid.allowalphatocoverage)
3088 GL_AlphaToCoverage(false);
3089 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3090 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3091 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3092 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3093 switch(vid.renderpath)
3095 case RENDERPATH_D3D9:
3097 R_SetupShader_SetPermutationHLSL(mode, permutation);
3098 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3099 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3100 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3101 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3102 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3103 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3104 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3105 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);
3106 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3107 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3109 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3110 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3111 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3112 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3113 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3116 case RENDERPATH_D3D10:
3117 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3119 case RENDERPATH_D3D11:
3120 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3122 case RENDERPATH_GL20:
3123 case RENDERPATH_GLES2:
3124 R_SetupShader_SetPermutationGLSL(mode, permutation);
3125 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3126 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3127 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3128 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3129 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3130 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]);
3131 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]);
3132 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);
3133 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]);
3134 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3136 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3137 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3138 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3139 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3140 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3142 case RENDERPATH_GL11:
3143 case RENDERPATH_GL13:
3144 case RENDERPATH_GLES1:
3146 case RENDERPATH_SOFT:
3147 R_SetupShader_SetPermutationGLSL(mode, permutation);
3148 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3149 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3150 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3151 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3152 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3153 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3154 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]);
3155 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);
3156 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3157 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3159 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3160 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3161 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3162 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3163 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3168 #define SKINFRAME_HASH 1024
3172 unsigned int loadsequence; // incremented each level change
3173 memexpandablearray_t array;
3174 skinframe_t *hash[SKINFRAME_HASH];
3177 r_skinframe_t r_skinframe;
3179 void R_SkinFrame_PrepareForPurge(void)
3181 r_skinframe.loadsequence++;
3182 // wrap it without hitting zero
3183 if (r_skinframe.loadsequence >= 200)
3184 r_skinframe.loadsequence = 1;
3187 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3191 // mark the skinframe as used for the purging code
3192 skinframe->loadsequence = r_skinframe.loadsequence;
3195 void R_SkinFrame_Purge(void)
3199 for (i = 0;i < SKINFRAME_HASH;i++)
3201 for (s = r_skinframe.hash[i];s;s = s->next)
3203 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3205 if (s->merged == s->base)
3207 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3208 R_PurgeTexture(s->stain );s->stain = NULL;
3209 R_PurgeTexture(s->merged);s->merged = NULL;
3210 R_PurgeTexture(s->base );s->base = NULL;
3211 R_PurgeTexture(s->pants );s->pants = NULL;
3212 R_PurgeTexture(s->shirt );s->shirt = NULL;
3213 R_PurgeTexture(s->nmap );s->nmap = NULL;
3214 R_PurgeTexture(s->gloss );s->gloss = NULL;
3215 R_PurgeTexture(s->glow );s->glow = NULL;
3216 R_PurgeTexture(s->fog );s->fog = NULL;
3217 R_PurgeTexture(s->reflect);s->reflect = NULL;
3218 s->loadsequence = 0;
3224 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3226 char basename[MAX_QPATH];
3228 Image_StripImageExtension(name, basename, sizeof(basename));
3230 if( last == NULL ) {
3232 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3233 item = r_skinframe.hash[hashindex];
3238 // linearly search through the hash bucket
3239 for( ; item ; item = item->next ) {
3240 if( !strcmp( item->basename, basename ) ) {
3247 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3251 char basename[MAX_QPATH];
3253 Image_StripImageExtension(name, basename, sizeof(basename));
3255 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3256 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3257 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3261 rtexture_t *dyntexture;
3262 // check whether its a dynamic texture
3263 dyntexture = CL_GetDynTexture( basename );
3264 if (!add && !dyntexture)
3266 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3267 memset(item, 0, sizeof(*item));
3268 strlcpy(item->basename, basename, sizeof(item->basename));
3269 item->base = dyntexture; // either NULL or dyntexture handle
3270 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3271 item->comparewidth = comparewidth;
3272 item->compareheight = compareheight;
3273 item->comparecrc = comparecrc;
3274 item->next = r_skinframe.hash[hashindex];
3275 r_skinframe.hash[hashindex] = item;
3277 else if (textureflags & TEXF_FORCE_RELOAD)
3279 rtexture_t *dyntexture;
3280 // check whether its a dynamic texture
3281 dyntexture = CL_GetDynTexture( basename );
3282 if (!add && !dyntexture)
3284 if (item->merged == item->base)
3285 item->merged = NULL;
3286 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3287 R_PurgeTexture(item->stain );item->stain = NULL;
3288 R_PurgeTexture(item->merged);item->merged = NULL;
3289 R_PurgeTexture(item->base );item->base = NULL;
3290 R_PurgeTexture(item->pants );item->pants = NULL;
3291 R_PurgeTexture(item->shirt );item->shirt = NULL;
3292 R_PurgeTexture(item->nmap );item->nmap = NULL;
3293 R_PurgeTexture(item->gloss );item->gloss = NULL;
3294 R_PurgeTexture(item->glow );item->glow = NULL;
3295 R_PurgeTexture(item->fog );item->fog = NULL;
3296 R_PurgeTexture(item->reflect);item->reflect = NULL;
3297 item->loadsequence = 0;
3299 else if( item->base == NULL )
3301 rtexture_t *dyntexture;
3302 // check whether its a dynamic texture
3303 // 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]
3304 dyntexture = CL_GetDynTexture( basename );
3305 item->base = dyntexture; // either NULL or dyntexture handle
3308 R_SkinFrame_MarkUsed(item);
3312 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3314 unsigned long long avgcolor[5], wsum; \
3322 for(pix = 0; pix < cnt; ++pix) \
3325 for(comp = 0; comp < 3; ++comp) \
3327 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3330 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3332 for(comp = 0; comp < 3; ++comp) \
3333 avgcolor[comp] += getpixel * w; \
3336 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3337 avgcolor[4] += getpixel; \
3339 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3341 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3342 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3343 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3344 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3347 extern cvar_t gl_picmip;
3348 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3351 unsigned char *pixels;
3352 unsigned char *bumppixels;
3353 unsigned char *basepixels = NULL;
3354 int basepixels_width = 0;
3355 int basepixels_height = 0;
3356 skinframe_t *skinframe;
3357 rtexture_t *ddsbase = NULL;
3358 qboolean ddshasalpha = false;
3359 float ddsavgcolor[4];
3360 char basename[MAX_QPATH];
3361 int miplevel = R_PicmipForFlags(textureflags);
3362 int savemiplevel = miplevel;
3366 if (cls.state == ca_dedicated)
3369 // return an existing skinframe if already loaded
3370 // if loading of the first image fails, don't make a new skinframe as it
3371 // would cause all future lookups of this to be missing
3372 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3373 if (skinframe && skinframe->base)
3376 Image_StripImageExtension(name, basename, sizeof(basename));
3378 // check for DDS texture file first
3379 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3381 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3382 if (basepixels == NULL)
3386 // FIXME handle miplevel
3388 if (developer_loading.integer)
3389 Con_Printf("loading skin \"%s\"\n", name);
3391 // we've got some pixels to store, so really allocate this new texture now
3393 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3394 textureflags &= ~TEXF_FORCE_RELOAD;
3395 skinframe->stain = NULL;
3396 skinframe->merged = NULL;
3397 skinframe->base = NULL;
3398 skinframe->pants = NULL;
3399 skinframe->shirt = NULL;
3400 skinframe->nmap = NULL;
3401 skinframe->gloss = NULL;
3402 skinframe->glow = NULL;
3403 skinframe->fog = NULL;
3404 skinframe->reflect = NULL;
3405 skinframe->hasalpha = false;
3406 // we could store the q2animname here too
3410 skinframe->base = ddsbase;
3411 skinframe->hasalpha = ddshasalpha;
3412 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3413 if (r_loadfog && skinframe->hasalpha)
3414 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);
3415 //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]);
3419 basepixels_width = image_width;
3420 basepixels_height = image_height;
3421 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);
3422 if (textureflags & TEXF_ALPHA)
3424 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3426 if (basepixels[j] < 255)
3428 skinframe->hasalpha = true;
3432 if (r_loadfog && skinframe->hasalpha)
3434 // has transparent pixels
3435 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3436 for (j = 0;j < image_width * image_height * 4;j += 4)
3441 pixels[j+3] = basepixels[j+3];
3443 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);
3447 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3449 //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]);
3450 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3451 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3452 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3453 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3459 mymiplevel = savemiplevel;
3460 if (r_loadnormalmap)
3461 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);
3462 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3464 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3465 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3466 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3467 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3470 // _norm is the name used by tenebrae and has been adopted as standard
3471 if (r_loadnormalmap && skinframe->nmap == NULL)
3473 mymiplevel = savemiplevel;
3474 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
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);
3480 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3482 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3483 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3484 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);
3486 Mem_Free(bumppixels);
3488 else if (r_shadow_bumpscale_basetexture.value > 0)
3490 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3491 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3492 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);
3496 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3497 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3501 // _luma is supported only for tenebrae compatibility
3502 // _glow is the preferred name
3503 mymiplevel = savemiplevel;
3504 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))))
3506 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);
3508 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3509 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3511 Mem_Free(pixels);pixels = NULL;
3514 mymiplevel = savemiplevel;
3515 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3517 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);
3519 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3520 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3526 mymiplevel = savemiplevel;
3527 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3529 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);
3531 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3532 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3538 mymiplevel = savemiplevel;
3539 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3541 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);
3543 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3544 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3550 mymiplevel = savemiplevel;
3551 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3553 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);
3555 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3556 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3563 Mem_Free(basepixels);
3568 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3569 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3572 unsigned char *temp1, *temp2;
3573 skinframe_t *skinframe;
3576 if (cls.state == ca_dedicated)
3579 // if already loaded just return it, otherwise make a new skinframe
3580 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3581 if (skinframe->base)
3583 textureflags &= ~TEXF_FORCE_RELOAD;
3585 skinframe->stain = NULL;
3586 skinframe->merged = NULL;
3587 skinframe->base = NULL;
3588 skinframe->pants = NULL;
3589 skinframe->shirt = NULL;
3590 skinframe->nmap = NULL;
3591 skinframe->gloss = NULL;
3592 skinframe->glow = NULL;
3593 skinframe->fog = NULL;
3594 skinframe->reflect = NULL;
3595 skinframe->hasalpha = false;
3597 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3601 if (developer_loading.integer)
3602 Con_Printf("loading 32bit skin \"%s\"\n", name);
3604 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3606 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3607 temp2 = temp1 + width * height * 4;
3608 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3609 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);
3612 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3613 if (textureflags & TEXF_ALPHA)
3615 for (i = 3;i < width * height * 4;i += 4)
3617 if (skindata[i] < 255)
3619 skinframe->hasalpha = true;
3623 if (r_loadfog && skinframe->hasalpha)
3625 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3626 memcpy(fogpixels, skindata, width * height * 4);
3627 for (i = 0;i < width * height * 4;i += 4)
3628 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3629 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3630 Mem_Free(fogpixels);
3634 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3635 //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]);
3640 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3644 skinframe_t *skinframe;
3646 if (cls.state == ca_dedicated)
3649 // if already loaded just return it, otherwise make a new skinframe
3650 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3651 if (skinframe->base)
3653 //textureflags &= ~TEXF_FORCE_RELOAD;
3655 skinframe->stain = NULL;
3656 skinframe->merged = NULL;
3657 skinframe->base = NULL;
3658 skinframe->pants = NULL;
3659 skinframe->shirt = NULL;
3660 skinframe->nmap = NULL;
3661 skinframe->gloss = NULL;
3662 skinframe->glow = NULL;
3663 skinframe->fog = NULL;
3664 skinframe->reflect = NULL;
3665 skinframe->hasalpha = false;
3667 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3671 if (developer_loading.integer)
3672 Con_Printf("loading quake skin \"%s\"\n", name);
3674 // 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)
3675 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3676 memcpy(skinframe->qpixels, skindata, width*height);
3677 skinframe->qwidth = width;
3678 skinframe->qheight = height;
3681 for (i = 0;i < width * height;i++)
3682 featuresmask |= palette_featureflags[skindata[i]];
3684 skinframe->hasalpha = false;
3685 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3686 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3687 skinframe->qgeneratemerged = true;
3688 skinframe->qgeneratebase = skinframe->qhascolormapping;
3689 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3691 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3692 //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]);
3697 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3701 unsigned char *skindata;
3704 if (!skinframe->qpixels)
3707 if (!skinframe->qhascolormapping)
3708 colormapped = false;
3712 if (!skinframe->qgeneratebase)
3717 if (!skinframe->qgeneratemerged)
3721 width = skinframe->qwidth;
3722 height = skinframe->qheight;
3723 skindata = skinframe->qpixels;
3725 if (skinframe->qgeneratenmap)
3727 unsigned char *temp1, *temp2;
3728 skinframe->qgeneratenmap = false;
3729 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3730 temp2 = temp1 + width * height * 4;
3731 // use either a custom palette or the quake palette
3732 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3733 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3734 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);
3738 if (skinframe->qgenerateglow)
3740 skinframe->qgenerateglow = false;
3741 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
3746 skinframe->qgeneratebase = false;
3747 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);
3748 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);
3749 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);
3753 skinframe->qgeneratemerged = false;
3754 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);
3757 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3759 Mem_Free(skinframe->qpixels);
3760 skinframe->qpixels = NULL;
3764 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)
3767 skinframe_t *skinframe;
3770 if (cls.state == ca_dedicated)
3773 // if already loaded just return it, otherwise make a new skinframe
3774 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3775 if (skinframe->base)
3777 textureflags &= ~TEXF_FORCE_RELOAD;
3779 skinframe->stain = NULL;
3780 skinframe->merged = NULL;
3781 skinframe->base = NULL;
3782 skinframe->pants = NULL;
3783 skinframe->shirt = NULL;
3784 skinframe->nmap = NULL;
3785 skinframe->gloss = NULL;
3786 skinframe->glow = NULL;
3787 skinframe->fog = NULL;
3788 skinframe->reflect = NULL;
3789 skinframe->hasalpha = false;
3791 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3795 if (developer_loading.integer)
3796 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3798 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3799 if (textureflags & TEXF_ALPHA)
3801 for (i = 0;i < width * height;i++)
3803 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3805 skinframe->hasalpha = true;
3809 if (r_loadfog && skinframe->hasalpha)
3810 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3813 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3814 //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]);
3819 skinframe_t *R_SkinFrame_LoadMissing(void)
3821 skinframe_t *skinframe;
3823 if (cls.state == ca_dedicated)
3826 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3827 skinframe->stain = NULL;
3828 skinframe->merged = NULL;
3829 skinframe->base = NULL;
3830 skinframe->pants = NULL;
3831 skinframe->shirt = NULL;
3832 skinframe->nmap = NULL;
3833 skinframe->gloss = NULL;
3834 skinframe->glow = NULL;
3835 skinframe->fog = NULL;
3836 skinframe->reflect = NULL;
3837 skinframe->hasalpha = false;
3839 skinframe->avgcolor[0] = rand() / RAND_MAX;
3840 skinframe->avgcolor[1] = rand() / RAND_MAX;
3841 skinframe->avgcolor[2] = rand() / RAND_MAX;
3842 skinframe->avgcolor[3] = 1;
3847 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3848 typedef struct suffixinfo_s
3851 qboolean flipx, flipy, flipdiagonal;
3854 static suffixinfo_t suffix[3][6] =
3857 {"px", false, false, false},
3858 {"nx", false, false, false},
3859 {"py", false, false, false},
3860 {"ny", false, false, false},
3861 {"pz", false, false, false},
3862 {"nz", false, false, false}
3865 {"posx", false, false, false},
3866 {"negx", false, false, false},
3867 {"posy", false, false, false},
3868 {"negy", false, false, false},
3869 {"posz", false, false, false},
3870 {"negz", false, false, false}
3873 {"rt", true, false, true},
3874 {"lf", false, true, true},
3875 {"ft", true, true, false},
3876 {"bk", false, false, false},
3877 {"up", true, false, true},
3878 {"dn", true, false, true}
3882 static int componentorder[4] = {0, 1, 2, 3};
3884 static rtexture_t *R_LoadCubemap(const char *basename)
3886 int i, j, cubemapsize;
3887 unsigned char *cubemappixels, *image_buffer;
3888 rtexture_t *cubemaptexture;
3890 // must start 0 so the first loadimagepixels has no requested width/height
3892 cubemappixels = NULL;
3893 cubemaptexture = NULL;
3894 // keep trying different suffix groups (posx, px, rt) until one loads
3895 for (j = 0;j < 3 && !cubemappixels;j++)
3897 // load the 6 images in the suffix group
3898 for (i = 0;i < 6;i++)
3900 // generate an image name based on the base and and suffix
3901 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3903 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3905 // an image loaded, make sure width and height are equal
3906 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3908 // if this is the first image to load successfully, allocate the cubemap memory
3909 if (!cubemappixels && image_width >= 1)
3911 cubemapsize = image_width;
3912 // note this clears to black, so unavailable sides are black
3913 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3915 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3917 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);
3920 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3922 Mem_Free(image_buffer);
3926 // if a cubemap loaded, upload it
3929 if (developer_loading.integer)
3930 Con_Printf("loading cubemap \"%s\"\n", basename);
3932 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);
3933 Mem_Free(cubemappixels);
3937 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3938 if (developer_loading.integer)
3940 Con_Printf("(tried tried images ");
3941 for (j = 0;j < 3;j++)
3942 for (i = 0;i < 6;i++)
3943 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3944 Con_Print(" and was unable to find any of them).\n");
3947 return cubemaptexture;
3950 rtexture_t *R_GetCubemap(const char *basename)
3953 for (i = 0;i < r_texture_numcubemaps;i++)
3954 if (r_texture_cubemaps[i] != NULL)
3955 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3956 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3957 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3958 return r_texture_whitecube;
3959 r_texture_numcubemaps++;
3960 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3961 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3962 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3963 return r_texture_cubemaps[i]->texture;
3966 static void R_Main_FreeViewCache(void)
3968 if (r_refdef.viewcache.entityvisible)
3969 Mem_Free(r_refdef.viewcache.entityvisible);
3970 if (r_refdef.viewcache.world_pvsbits)
3971 Mem_Free(r_refdef.viewcache.world_pvsbits);
3972 if (r_refdef.viewcache.world_leafvisible)
3973 Mem_Free(r_refdef.viewcache.world_leafvisible);
3974 if (r_refdef.viewcache.world_surfacevisible)
3975 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3976 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3979 static void R_Main_ResizeViewCache(void)
3981 int numentities = r_refdef.scene.numentities;
3982 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3983 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3984 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3985 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3986 if (r_refdef.viewcache.maxentities < numentities)
3988 r_refdef.viewcache.maxentities = numentities;
3989 if (r_refdef.viewcache.entityvisible)
3990 Mem_Free(r_refdef.viewcache.entityvisible);
3991 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3993 if (r_refdef.viewcache.world_numclusters != numclusters)
3995 r_refdef.viewcache.world_numclusters = numclusters;
3996 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3997 if (r_refdef.viewcache.world_pvsbits)
3998 Mem_Free(r_refdef.viewcache.world_pvsbits);
3999 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4001 if (r_refdef.viewcache.world_numleafs != numleafs)
4003 r_refdef.viewcache.world_numleafs = numleafs;
4004 if (r_refdef.viewcache.world_leafvisible)
4005 Mem_Free(r_refdef.viewcache.world_leafvisible);
4006 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4008 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4010 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4011 if (r_refdef.viewcache.world_surfacevisible)
4012 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4013 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4017 extern rtexture_t *loadingscreentexture;
4018 static void gl_main_start(void)
4020 loadingscreentexture = NULL;
4021 r_texture_blanknormalmap = NULL;
4022 r_texture_white = NULL;
4023 r_texture_grey128 = NULL;
4024 r_texture_black = NULL;
4025 r_texture_whitecube = NULL;
4026 r_texture_normalizationcube = NULL;
4027 r_texture_fogattenuation = NULL;
4028 r_texture_fogheighttexture = NULL;
4029 r_texture_gammaramps = NULL;
4030 r_texture_numcubemaps = 0;
4031 r_uniformbufferalignment = 32;
4033 r_loaddds = r_texture_dds_load.integer != 0;
4034 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4036 switch(vid.renderpath)
4038 case RENDERPATH_GL20:
4039 case RENDERPATH_D3D9:
4040 case RENDERPATH_D3D10:
4041 case RENDERPATH_D3D11:
4042 case RENDERPATH_SOFT:
4043 case RENDERPATH_GLES2:
4044 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4045 Cvar_SetValueQuick(&gl_combine, 1);
4046 Cvar_SetValueQuick(&r_glsl, 1);
4047 r_loadnormalmap = true;
4050 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4051 if (vid.support.arb_uniform_buffer_object)
4052 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4055 case RENDERPATH_GL13:
4056 case RENDERPATH_GLES1:
4057 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4058 Cvar_SetValueQuick(&gl_combine, 1);
4059 Cvar_SetValueQuick(&r_glsl, 0);
4060 r_loadnormalmap = false;
4061 r_loadgloss = false;
4064 case RENDERPATH_GL11:
4065 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4066 Cvar_SetValueQuick(&gl_combine, 0);
4067 Cvar_SetValueQuick(&r_glsl, 0);
4068 r_loadnormalmap = false;
4069 r_loadgloss = false;
4075 R_FrameData_Reset();
4076 R_BufferData_Reset();
4080 memset(r_queries, 0, sizeof(r_queries));
4082 r_qwskincache = NULL;
4083 r_qwskincache_size = 0;
4085 // due to caching of texture_t references, the collision cache must be reset
4086 Collision_Cache_Reset(true);
4088 // set up r_skinframe loading system for textures
4089 memset(&r_skinframe, 0, sizeof(r_skinframe));
4090 r_skinframe.loadsequence = 1;
4091 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4093 r_main_texturepool = R_AllocTexturePool();
4094 R_BuildBlankTextures();
4096 if (vid.support.arb_texture_cube_map)
4099 R_BuildNormalizationCube();
4101 r_texture_fogattenuation = NULL;
4102 r_texture_fogheighttexture = NULL;
4103 r_texture_gammaramps = NULL;
4104 //r_texture_fogintensity = NULL;
4105 memset(&r_fb, 0, sizeof(r_fb));
4106 r_glsl_permutation = NULL;
4107 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4108 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4109 glslshaderstring = NULL;
4111 r_hlsl_permutation = NULL;
4112 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4113 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4115 hlslshaderstring = NULL;
4116 memset(&r_svbsp, 0, sizeof (r_svbsp));
4118 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4119 r_texture_numcubemaps = 0;
4121 r_refdef.fogmasktable_density = 0;
4124 // For Steelstorm Android
4125 // FIXME CACHE the program and reload
4126 // FIXME see possible combinations for SS:BR android
4127 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4128 R_SetupShader_SetPermutationGLSL(0, 12);
4129 R_SetupShader_SetPermutationGLSL(0, 13);
4130 R_SetupShader_SetPermutationGLSL(0, 8388621);
4131 R_SetupShader_SetPermutationGLSL(3, 0);
4132 R_SetupShader_SetPermutationGLSL(3, 2048);
4133 R_SetupShader_SetPermutationGLSL(5, 0);
4134 R_SetupShader_SetPermutationGLSL(5, 2);
4135 R_SetupShader_SetPermutationGLSL(5, 2048);
4136 R_SetupShader_SetPermutationGLSL(5, 8388608);
4137 R_SetupShader_SetPermutationGLSL(11, 1);
4138 R_SetupShader_SetPermutationGLSL(11, 2049);
4139 R_SetupShader_SetPermutationGLSL(11, 8193);
4140 R_SetupShader_SetPermutationGLSL(11, 10241);
4141 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4145 static void gl_main_shutdown(void)
4148 R_FrameData_Reset();
4149 R_BufferData_Reset();
4151 R_Main_FreeViewCache();
4153 switch(vid.renderpath)
4155 case RENDERPATH_GL11:
4156 case RENDERPATH_GL13:
4157 case RENDERPATH_GL20:
4158 case RENDERPATH_GLES1:
4159 case RENDERPATH_GLES2:
4160 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4162 qglDeleteQueriesARB(r_maxqueries, r_queries);
4165 case RENDERPATH_D3D9:
4166 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4168 case RENDERPATH_D3D10:
4169 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4171 case RENDERPATH_D3D11:
4172 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4174 case RENDERPATH_SOFT:
4180 memset(r_queries, 0, sizeof(r_queries));
4182 r_qwskincache = NULL;
4183 r_qwskincache_size = 0;
4185 // clear out the r_skinframe state
4186 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4187 memset(&r_skinframe, 0, sizeof(r_skinframe));
4190 Mem_Free(r_svbsp.nodes);
4191 memset(&r_svbsp, 0, sizeof (r_svbsp));
4192 R_FreeTexturePool(&r_main_texturepool);
4193 loadingscreentexture = NULL;
4194 r_texture_blanknormalmap = NULL;
4195 r_texture_white = NULL;
4196 r_texture_grey128 = NULL;
4197 r_texture_black = NULL;
4198 r_texture_whitecube = NULL;
4199 r_texture_normalizationcube = NULL;
4200 r_texture_fogattenuation = NULL;
4201 r_texture_fogheighttexture = NULL;
4202 r_texture_gammaramps = NULL;
4203 r_texture_numcubemaps = 0;
4204 //r_texture_fogintensity = NULL;
4205 memset(&r_fb, 0, sizeof(r_fb));
4208 r_glsl_permutation = NULL;
4209 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4210 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4211 glslshaderstring = NULL;
4213 r_hlsl_permutation = NULL;
4214 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4215 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4217 hlslshaderstring = NULL;
4220 static void gl_main_newmap(void)
4222 // FIXME: move this code to client
4223 char *entities, entname[MAX_QPATH];
4225 Mem_Free(r_qwskincache);
4226 r_qwskincache = NULL;
4227 r_qwskincache_size = 0;
4230 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4231 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4233 CL_ParseEntityLump(entities);
4237 if (cl.worldmodel->brush.entities)
4238 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4240 R_Main_FreeViewCache();
4242 R_FrameData_Reset();
4243 R_BufferData_Reset();
4246 void GL_Main_Init(void)
4249 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4251 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4252 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4253 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4254 if (gamemode == GAME_NEHAHRA)
4256 Cvar_RegisterVariable (&gl_fogenable);
4257 Cvar_RegisterVariable (&gl_fogdensity);
4258 Cvar_RegisterVariable (&gl_fogred);
4259 Cvar_RegisterVariable (&gl_foggreen);
4260 Cvar_RegisterVariable (&gl_fogblue);
4261 Cvar_RegisterVariable (&gl_fogstart);
4262 Cvar_RegisterVariable (&gl_fogend);
4263 Cvar_RegisterVariable (&gl_skyclip);
4265 Cvar_RegisterVariable(&r_motionblur);
4266 Cvar_RegisterVariable(&r_damageblur);
4267 Cvar_RegisterVariable(&r_motionblur_averaging);
4268 Cvar_RegisterVariable(&r_motionblur_randomize);
4269 Cvar_RegisterVariable(&r_motionblur_minblur);
4270 Cvar_RegisterVariable(&r_motionblur_maxblur);
4271 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4272 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4273 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4274 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4275 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4276 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4277 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4278 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4279 Cvar_RegisterVariable(&r_equalize_entities_by);
4280 Cvar_RegisterVariable(&r_equalize_entities_to);
4281 Cvar_RegisterVariable(&r_depthfirst);
4282 Cvar_RegisterVariable(&r_useinfinitefarclip);
4283 Cvar_RegisterVariable(&r_farclip_base);
4284 Cvar_RegisterVariable(&r_farclip_world);
4285 Cvar_RegisterVariable(&r_nearclip);
4286 Cvar_RegisterVariable(&r_deformvertexes);
4287 Cvar_RegisterVariable(&r_transparent);
4288 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4289 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4290 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4291 Cvar_RegisterVariable(&r_showoverdraw);
4292 Cvar_RegisterVariable(&r_showbboxes);
4293 Cvar_RegisterVariable(&r_showsurfaces);
4294 Cvar_RegisterVariable(&r_showtris);
4295 Cvar_RegisterVariable(&r_shownormals);
4296 Cvar_RegisterVariable(&r_showlighting);
4297 Cvar_RegisterVariable(&r_showshadowvolumes);
4298 Cvar_RegisterVariable(&r_showcollisionbrushes);
4299 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4300 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4301 Cvar_RegisterVariable(&r_showdisabledepthtest);
4302 Cvar_RegisterVariable(&r_drawportals);
4303 Cvar_RegisterVariable(&r_drawentities);
4304 Cvar_RegisterVariable(&r_draw2d);
4305 Cvar_RegisterVariable(&r_drawworld);
4306 Cvar_RegisterVariable(&r_cullentities_trace);
4307 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4308 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4309 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4310 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4311 Cvar_RegisterVariable(&r_sortentities);
4312 Cvar_RegisterVariable(&r_drawviewmodel);
4313 Cvar_RegisterVariable(&r_drawexteriormodel);
4314 Cvar_RegisterVariable(&r_speeds);
4315 Cvar_RegisterVariable(&r_fullbrights);
4316 Cvar_RegisterVariable(&r_wateralpha);
4317 Cvar_RegisterVariable(&r_dynamic);
4318 Cvar_RegisterVariable(&r_fakelight);
4319 Cvar_RegisterVariable(&r_fakelight_intensity);
4320 Cvar_RegisterVariable(&r_fullbright);
4321 Cvar_RegisterVariable(&r_shadows);
4322 Cvar_RegisterVariable(&r_shadows_darken);
4323 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4324 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4325 Cvar_RegisterVariable(&r_shadows_throwdistance);
4326 Cvar_RegisterVariable(&r_shadows_throwdirection);
4327 Cvar_RegisterVariable(&r_shadows_focus);
4328 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4329 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4330 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4331 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4332 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4333 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4334 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4335 Cvar_RegisterVariable(&r_fog_exp2);
4336 Cvar_RegisterVariable(&r_fog_clear);
4337 Cvar_RegisterVariable(&r_drawfog);
4338 Cvar_RegisterVariable(&r_transparentdepthmasking);
4339 Cvar_RegisterVariable(&r_transparent_sortmindist);
4340 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4341 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4342 Cvar_RegisterVariable(&r_texture_dds_load);
4343 Cvar_RegisterVariable(&r_texture_dds_save);
4344 Cvar_RegisterVariable(&r_textureunits);
4345 Cvar_RegisterVariable(&gl_combine);
4346 Cvar_RegisterVariable(&r_usedepthtextures);
4347 Cvar_RegisterVariable(&r_viewfbo);
4348 Cvar_RegisterVariable(&r_viewscale);
4349 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4350 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4351 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4352 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4353 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4354 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4355 Cvar_RegisterVariable(&r_glsl);
4356 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4357 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4358 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4359 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4360 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4361 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4362 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4363 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4364 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4365 Cvar_RegisterVariable(&r_glsl_postprocess);
4366 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4367 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4368 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4369 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4370 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4371 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4372 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4373 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4374 Cvar_RegisterVariable(&r_celshading);
4375 Cvar_RegisterVariable(&r_celoutlines);
4377 Cvar_RegisterVariable(&r_water);
4378 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4379 Cvar_RegisterVariable(&r_water_clippingplanebias);
4380 Cvar_RegisterVariable(&r_water_refractdistort);
4381 Cvar_RegisterVariable(&r_water_reflectdistort);
4382 Cvar_RegisterVariable(&r_water_scissormode);
4383 Cvar_RegisterVariable(&r_water_lowquality);
4384 Cvar_RegisterVariable(&r_water_hideplayer);
4385 Cvar_RegisterVariable(&r_water_fbo);
4387 Cvar_RegisterVariable(&r_lerpsprites);
4388 Cvar_RegisterVariable(&r_lerpmodels);
4389 Cvar_RegisterVariable(&r_lerplightstyles);
4390 Cvar_RegisterVariable(&r_waterscroll);
4391 Cvar_RegisterVariable(&r_bloom);
4392 Cvar_RegisterVariable(&r_bloom_colorscale);
4393 Cvar_RegisterVariable(&r_bloom_brighten);
4394 Cvar_RegisterVariable(&r_bloom_blur);
4395 Cvar_RegisterVariable(&r_bloom_resolution);
4396 Cvar_RegisterVariable(&r_bloom_colorexponent);
4397 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4398 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4399 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4400 Cvar_RegisterVariable(&r_hdr_glowintensity);
4401 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4402 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4403 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4404 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4405 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4406 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4407 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4408 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4409 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4410 Cvar_RegisterVariable(&developer_texturelogging);
4411 Cvar_RegisterVariable(&gl_lightmaps);
4412 Cvar_RegisterVariable(&r_test);
4413 Cvar_RegisterVariable(&r_batch_multidraw);
4414 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4415 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4416 Cvar_RegisterVariable(&r_glsl_skeletal);
4417 Cvar_RegisterVariable(&r_glsl_saturation);
4418 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4419 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4420 Cvar_RegisterVariable(&r_framedatasize);
4421 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4422 Cvar_RegisterVariable(&r_buffermegs[i]);
4423 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4424 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4425 Cvar_SetValue("r_fullbrights", 0);
4426 #ifdef DP_MOBILETOUCH
4427 // GLES devices have terrible depth precision in general, so...
4428 Cvar_SetValueQuick(&r_nearclip, 4);
4429 Cvar_SetValueQuick(&r_farclip_base, 4096);
4430 Cvar_SetValueQuick(&r_farclip_world, 0);
4431 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4433 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4436 void Render_Init(void)
4449 R_LightningBeams_Init();
4459 extern char *ENGINE_EXTENSIONS;
4462 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4463 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4464 gl_version = (const char *)qglGetString(GL_VERSION);
4465 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4469 if (!gl_platformextensions)
4470 gl_platformextensions = "";
4472 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4473 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4474 Con_Printf("GL_VERSION: %s\n", gl_version);
4475 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4476 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4478 VID_CheckExtensions();
4480 // LordHavoc: report supported extensions
4482 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4484 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4487 // clear to black (loading plaque will be seen over this)
4488 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4492 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4496 if (r_trippy.integer)
4498 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4500 p = r_refdef.view.frustum + i;
4505 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4509 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4513 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4517 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4521 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4525 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4529 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4533 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4541 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4545 if (r_trippy.integer)
4547 for (i = 0;i < numplanes;i++)
4554 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4558 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4562 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4566 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4570 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4574 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4578 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4582 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4590 //==================================================================================
4592 // LordHavoc: this stores temporary data used within the same frame
4594 typedef struct r_framedata_mem_s
4596 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4597 size_t size; // how much usable space
4598 size_t current; // how much space in use
4599 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4600 size_t wantedsize; // how much space was allocated
4601 unsigned char *data; // start of real data (16byte aligned)
4605 static r_framedata_mem_t *r_framedata_mem;
4607 void R_FrameData_Reset(void)
4609 while (r_framedata_mem)
4611 r_framedata_mem_t *next = r_framedata_mem->purge;
4612 Mem_Free(r_framedata_mem);
4613 r_framedata_mem = next;
4617 static void R_FrameData_Resize(qboolean mustgrow)
4620 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4621 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4622 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4624 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4625 newmem->wantedsize = wantedsize;
4626 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4627 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4628 newmem->current = 0;
4630 newmem->purge = r_framedata_mem;
4631 r_framedata_mem = newmem;
4635 void R_FrameData_NewFrame(void)
4637 R_FrameData_Resize(false);
4638 if (!r_framedata_mem)
4640 // if we ran out of space on the last frame, free the old memory now
4641 while (r_framedata_mem->purge)
4643 // repeatedly remove the second item in the list, leaving only head
4644 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4645 Mem_Free(r_framedata_mem->purge);
4646 r_framedata_mem->purge = next;
4648 // reset the current mem pointer
4649 r_framedata_mem->current = 0;
4650 r_framedata_mem->mark = 0;
4653 void *R_FrameData_Alloc(size_t size)
4658 // align to 16 byte boundary - the data pointer is already aligned, so we
4659 // only need to ensure the size of every allocation is also aligned
4660 size = (size + 15) & ~15;
4662 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4664 // emergency - we ran out of space, allocate more memory
4665 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4666 // this might not be a growing it, but we'll allocate another buffer every time
4667 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4668 R_FrameData_Resize(true);
4671 data = r_framedata_mem->data + r_framedata_mem->current;
4672 r_framedata_mem->current += size;
4674 // count the usage for stats
4675 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4676 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4678 return (void *)data;
4681 void *R_FrameData_Store(size_t size, void *data)
4683 void *d = R_FrameData_Alloc(size);
4685 memcpy(d, data, size);
4689 void R_FrameData_SetMark(void)
4691 if (!r_framedata_mem)
4693 r_framedata_mem->mark = r_framedata_mem->current;
4696 void R_FrameData_ReturnToMark(void)
4698 if (!r_framedata_mem)
4700 r_framedata_mem->current = r_framedata_mem->mark;
4703 //==================================================================================
4705 // avoid reusing the same buffer objects on consecutive frames
4706 #define R_BUFFERDATA_CYCLE 3
4708 typedef struct r_bufferdata_buffer_s
4710 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4711 size_t size; // how much usable space
4712 size_t current; // how much space in use
4713 r_meshbuffer_t *buffer; // the buffer itself
4715 r_bufferdata_buffer_t;
4717 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4718 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4720 /// frees all dynamic buffers
4721 void R_BufferData_Reset(void)
4724 r_bufferdata_buffer_t **p, *mem;
4725 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4727 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4730 p = &r_bufferdata_buffer[cycle][type];
4736 R_Mesh_DestroyMeshBuffer(mem->buffer);
4743 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4744 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4746 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4748 float newvalue = r_buffermegs[type].value;
4750 // increase the cvar if we have to (but only if we already have a mem)
4751 if (mustgrow && mem)
4753 newvalue = bound(0.25f, newvalue, 256.0f);
4754 while (newvalue * 1024*1024 < minsize)
4757 // clamp the cvar to valid range
4758 newvalue = bound(0.25f, newvalue, 256.0f);
4759 if (r_buffermegs[type].value != newvalue)
4760 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4762 // calculate size in bytes
4763 size = (size_t)(newvalue * 1024*1024);
4764 size = bound(131072, size, 256*1024*1024);
4766 // allocate a new buffer if the size is different (purge old one later)
4767 // or if we were told we must grow the buffer
4768 if (!mem || mem->size != size || mustgrow)
4770 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4773 if (type == R_BUFFERDATA_VERTEX)
4774 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4775 else if (type == R_BUFFERDATA_INDEX16)
4776 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4777 else if (type == R_BUFFERDATA_INDEX32)
4778 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4779 else if (type == R_BUFFERDATA_UNIFORM)
4780 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4781 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4782 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4786 void R_BufferData_NewFrame(void)
4789 r_bufferdata_buffer_t **p, *mem;
4790 // cycle to the next frame's buffers
4791 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4792 // if we ran out of space on the last time we used these buffers, free the old memory now
4793 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4795 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4797 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4798 // free all but the head buffer, this is how we recycle obsolete
4799 // buffers after they are no longer in use
4800 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4806 R_Mesh_DestroyMeshBuffer(mem->buffer);
4809 // reset the current offset
4810 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4815 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4817 r_bufferdata_buffer_t *mem;
4821 *returnbufferoffset = 0;
4823 // align size to a byte boundary appropriate for the buffer type, this
4824 // makes all allocations have aligned start offsets
4825 if (type == R_BUFFERDATA_UNIFORM)
4826 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4828 padsize = (datasize + 15) & ~15;
4830 // if we ran out of space in this buffer we must allocate a new one
4831 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)
4832 R_BufferData_Resize(type, true, padsize);
4834 // if the resize did not give us enough memory, fail
4835 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)
4836 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4838 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4839 offset = (int)mem->current;
4840 mem->current += padsize;
4842 // upload the data to the buffer at the chosen offset
4844 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4845 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4847 // count the usage for stats
4848 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4849 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4851 // return the buffer offset
4852 *returnbufferoffset = offset;
4857 //==================================================================================
4859 // LordHavoc: animcache originally written by Echon, rewritten since then
4862 * Animation cache prevents re-generating mesh data for an animated model
4863 * multiple times in one frame for lighting, shadowing, reflections, etc.
4866 void R_AnimCache_Free(void)
4870 void R_AnimCache_ClearCache(void)
4873 entity_render_t *ent;
4875 for (i = 0;i < r_refdef.scene.numentities;i++)
4877 ent = r_refdef.scene.entities[i];
4878 ent->animcache_vertex3f = NULL;
4879 ent->animcache_vertex3f_vertexbuffer = NULL;
4880 ent->animcache_vertex3f_bufferoffset = 0;
4881 ent->animcache_normal3f = NULL;
4882 ent->animcache_normal3f_vertexbuffer = NULL;
4883 ent->animcache_normal3f_bufferoffset = 0;
4884 ent->animcache_svector3f = NULL;
4885 ent->animcache_svector3f_vertexbuffer = NULL;
4886 ent->animcache_svector3f_bufferoffset = 0;
4887 ent->animcache_tvector3f = NULL;
4888 ent->animcache_tvector3f_vertexbuffer = NULL;
4889 ent->animcache_tvector3f_bufferoffset = 0;
4890 ent->animcache_vertexmesh = NULL;
4891 ent->animcache_vertexmesh_vertexbuffer = NULL;
4892 ent->animcache_vertexmesh_bufferoffset = 0;
4893 ent->animcache_skeletaltransform3x4 = NULL;
4894 ent->animcache_skeletaltransform3x4buffer = NULL;
4895 ent->animcache_skeletaltransform3x4offset = 0;
4896 ent->animcache_skeletaltransform3x4size = 0;
4900 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4904 // check if we need the meshbuffers
4905 if (!vid.useinterleavedarrays)
4908 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4909 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4910 // TODO: upload vertexbuffer?
4911 if (ent->animcache_vertexmesh)
4913 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4914 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4915 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4916 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4917 for (i = 0;i < numvertices;i++)
4918 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4919 if (ent->animcache_svector3f)
4920 for (i = 0;i < numvertices;i++)
4921 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4922 if (ent->animcache_tvector3f)
4923 for (i = 0;i < numvertices;i++)
4924 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4925 if (ent->animcache_normal3f)
4926 for (i = 0;i < numvertices;i++)
4927 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4931 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4933 dp_model_t *model = ent->model;
4936 // see if this ent is worth caching
4937 if (!model || !model->Draw || !model->AnimateVertices)
4939 // nothing to cache if it contains no animations and has no skeleton
4940 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4942 // see if it is already cached for gpuskeletal
4943 if (ent->animcache_skeletaltransform3x4)
4945 // see if it is already cached as a mesh
4946 if (ent->animcache_vertex3f)
4948 // check if we need to add normals or tangents
4949 if (ent->animcache_normal3f)
4950 wantnormals = false;
4951 if (ent->animcache_svector3f)
4952 wanttangents = false;
4953 if (!wantnormals && !wanttangents)
4957 // check which kind of cache we need to generate
4958 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4960 // cache the skeleton so the vertex shader can use it
4961 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4962 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4963 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4964 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4965 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4966 // note: this can fail if the buffer is at the grow limit
4967 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4968 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4970 else if (ent->animcache_vertex3f)
4972 // mesh was already cached but we may need to add normals/tangents
4973 // (this only happens with multiple views, reflections, cameras, etc)
4974 if (wantnormals || wanttangents)
4976 numvertices = model->surfmesh.num_vertices;
4978 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4981 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4982 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4984 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4985 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4986 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4987 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4988 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4993 // generate mesh cache
4994 numvertices = model->surfmesh.num_vertices;
4995 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4997 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5000 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5001 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5003 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5004 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5005 if (wantnormals || wanttangents)
5007 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5008 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5009 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5011 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5012 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5013 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5018 void R_AnimCache_CacheVisibleEntities(void)
5021 qboolean wantnormals = true;
5022 qboolean wanttangents = !r_showsurfaces.integer;
5024 switch(vid.renderpath)
5026 case RENDERPATH_GL20:
5027 case RENDERPATH_D3D9:
5028 case RENDERPATH_D3D10:
5029 case RENDERPATH_D3D11:
5030 case RENDERPATH_GLES2:
5032 case RENDERPATH_GL11:
5033 case RENDERPATH_GL13:
5034 case RENDERPATH_GLES1:
5035 wanttangents = false;
5037 case RENDERPATH_SOFT:
5041 if (r_shownormals.integer)
5042 wanttangents = wantnormals = true;
5044 // TODO: thread this
5045 // NOTE: R_PrepareRTLights() also caches entities
5047 for (i = 0;i < r_refdef.scene.numentities;i++)
5048 if (r_refdef.viewcache.entityvisible[i])
5049 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5052 //==================================================================================
5054 extern cvar_t r_overheadsprites_pushback;
5056 static void R_View_UpdateEntityLighting (void)
5059 entity_render_t *ent;
5060 vec3_t tempdiffusenormal, avg;
5061 vec_t f, fa, fd, fdd;
5062 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5064 for (i = 0;i < r_refdef.scene.numentities;i++)
5066 ent = r_refdef.scene.entities[i];
5068 // skip unseen models
5069 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5073 if (ent->model && ent->model == cl.worldmodel)
5075 // TODO: use modellight for r_ambient settings on world?
5076 VectorSet(ent->modellight_ambient, 0, 0, 0);
5077 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5078 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5082 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5084 // aleady updated by CSQC
5085 // TODO: force modellight on BSP models in this case?
5086 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5090 // fetch the lighting from the worldmodel data
5091 VectorClear(ent->modellight_ambient);
5092 VectorClear(ent->modellight_diffuse);
5093 VectorClear(tempdiffusenormal);
5094 if (ent->flags & RENDER_LIGHT)
5097 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5099 // complete lightning for lit sprites
5100 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5101 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5103 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5104 org[2] = org[2] + r_overheadsprites_pushback.value;
5105 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5108 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5110 if(ent->flags & RENDER_EQUALIZE)
5112 // first fix up ambient lighting...
5113 if(r_equalize_entities_minambient.value > 0)
5115 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5118 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5119 if(fa < r_equalize_entities_minambient.value * fd)
5122 // fa'/fd' = minambient
5123 // fa'+0.25*fd' = fa+0.25*fd
5125 // fa' = fd' * minambient
5126 // fd'*(0.25+minambient) = fa+0.25*fd
5128 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5129 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5131 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5132 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
5133 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5134 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5139 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5141 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5142 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5146 // adjust brightness and saturation to target
5147 avg[0] = avg[1] = avg[2] = fa / f;
5148 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5149 avg[0] = avg[1] = avg[2] = fd / f;
5150 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5156 VectorSet(ent->modellight_ambient, 1, 1, 1);
5159 // move the light direction into modelspace coordinates for lighting code
5160 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5161 if(VectorLength2(ent->modellight_lightdir) == 0)
5162 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5163 VectorNormalize(ent->modellight_lightdir);
5167 #define MAX_LINEOFSIGHTTRACES 64
5169 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5172 vec3_t boxmins, boxmaxs;
5175 dp_model_t *model = r_refdef.scene.worldmodel;
5177 if (!model || !model->brush.TraceLineOfSight)
5180 // expand the box a little
5181 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5182 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5183 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5184 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5185 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5186 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5188 // return true if eye is inside enlarged box
5189 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5193 VectorCopy(eye, start);
5194 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5195 if (model->brush.TraceLineOfSight(model, start, end))
5198 // try various random positions
5199 for (i = 0;i < numsamples;i++)
5201 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5202 if (model->brush.TraceLineOfSight(model, start, end))
5210 static void R_View_UpdateEntityVisible (void)
5215 entity_render_t *ent;
5217 if (r_refdef.envmap || r_fb.water.hideplayer)
5218 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5219 else if (chase_active.integer || r_fb.water.renderingscene)
5220 renderimask = RENDER_VIEWMODEL;
5222 renderimask = RENDER_EXTERIORMODEL;
5223 if (!r_drawviewmodel.integer)
5224 renderimask |= RENDER_VIEWMODEL;
5225 if (!r_drawexteriormodel.integer)
5226 renderimask |= RENDER_EXTERIORMODEL;
5227 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5228 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5230 // worldmodel can check visibility
5231 for (i = 0;i < r_refdef.scene.numentities;i++)
5233 ent = r_refdef.scene.entities[i];
5234 if (!(ent->flags & renderimask))
5235 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)))
5236 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))
5237 r_refdef.viewcache.entityvisible[i] = true;
5242 // no worldmodel or it can't check visibility
5243 for (i = 0;i < r_refdef.scene.numentities;i++)
5245 ent = r_refdef.scene.entities[i];
5246 if (!(ent->flags & renderimask))
5247 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)))
5248 r_refdef.viewcache.entityvisible[i] = true;
5251 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5252 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5254 for (i = 0;i < r_refdef.scene.numentities;i++)
5256 if (!r_refdef.viewcache.entityvisible[i])
5258 ent = r_refdef.scene.entities[i];
5259 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5261 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5263 continue; // temp entities do pvs only
5264 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5265 ent->last_trace_visibility = realtime;
5266 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5267 r_refdef.viewcache.entityvisible[i] = 0;
5273 /// only used if skyrendermasked, and normally returns false
5274 static int R_DrawBrushModelsSky (void)
5277 entity_render_t *ent;
5280 for (i = 0;i < r_refdef.scene.numentities;i++)
5282 if (!r_refdef.viewcache.entityvisible[i])
5284 ent = r_refdef.scene.entities[i];
5285 if (!ent->model || !ent->model->DrawSky)
5287 ent->model->DrawSky(ent);
5293 static void R_DrawNoModel(entity_render_t *ent);
5294 static void R_DrawModels(void)
5297 entity_render_t *ent;
5299 for (i = 0;i < r_refdef.scene.numentities;i++)
5301 if (!r_refdef.viewcache.entityvisible[i])
5303 ent = r_refdef.scene.entities[i];
5304 r_refdef.stats[r_stat_entities]++;
5306 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5309 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5310 Con_Printf("R_DrawModels\n");
5311 Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
5312 Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
5313 Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
5316 if (ent->model && ent->model->Draw != NULL)
5317 ent->model->Draw(ent);
5323 static void R_DrawModelsDepth(void)
5326 entity_render_t *ent;
5328 for (i = 0;i < r_refdef.scene.numentities;i++)
5330 if (!r_refdef.viewcache.entityvisible[i])
5332 ent = r_refdef.scene.entities[i];
5333 if (ent->model && ent->model->DrawDepth != NULL)
5334 ent->model->DrawDepth(ent);
5338 static void R_DrawModelsDebug(void)
5341 entity_render_t *ent;
5343 for (i = 0;i < r_refdef.scene.numentities;i++)
5345 if (!r_refdef.viewcache.entityvisible[i])
5347 ent = r_refdef.scene.entities[i];
5348 if (ent->model && ent->model->DrawDebug != NULL)
5349 ent->model->DrawDebug(ent);
5353 static void R_DrawModelsAddWaterPlanes(void)
5356 entity_render_t *ent;
5358 for (i = 0;i < r_refdef.scene.numentities;i++)
5360 if (!r_refdef.viewcache.entityvisible[i])
5362 ent = r_refdef.scene.entities[i];
5363 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5364 ent->model->DrawAddWaterPlanes(ent);
5368 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5370 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5372 if (r_hdr_irisadaptation.integer)
5377 vec3_t diffusenormal;
5379 vec_t brightness = 0.0f;
5384 VectorCopy(r_refdef.view.forward, forward);
5385 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5387 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5388 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5389 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5390 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5391 d = DotProduct(forward, diffusenormal);
5392 brightness += VectorLength(ambient);
5394 brightness += d * VectorLength(diffuse);
5396 brightness *= 1.0f / c;
5397 brightness += 0.00001f; // make sure it's never zero
5398 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5399 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5400 current = r_hdr_irisadaptation_value.value;
5402 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5403 else if (current > goal)
5404 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5405 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5406 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5408 else if (r_hdr_irisadaptation_value.value != 1.0f)
5409 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5412 static void R_View_SetFrustum(const int *scissor)
5415 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5416 vec3_t forward, left, up, origin, v;
5420 // flipped x coordinates (because x points left here)
5421 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5422 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5424 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5425 switch(vid.renderpath)
5427 case RENDERPATH_D3D9:
5428 case RENDERPATH_D3D10:
5429 case RENDERPATH_D3D11:
5430 // non-flipped y coordinates
5431 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5432 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5434 case RENDERPATH_SOFT:
5435 case RENDERPATH_GL11:
5436 case RENDERPATH_GL13:
5437 case RENDERPATH_GL20:
5438 case RENDERPATH_GLES1:
5439 case RENDERPATH_GLES2:
5440 // non-flipped y coordinates
5441 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5442 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5447 // we can't trust r_refdef.view.forward and friends in reflected scenes
5448 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5451 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5452 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5453 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5454 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5455 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5456 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5457 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5458 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5459 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5460 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5461 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5462 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5466 zNear = r_refdef.nearclip;
5467 nudge = 1.0 - 1.0 / (1<<23);
5468 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5469 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5470 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5471 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5472 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5473 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5474 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5475 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5481 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5482 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5483 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5484 r_refdef.view.frustum[0].dist = m[15] - m[12];
5486 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5487 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5488 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5489 r_refdef.view.frustum[1].dist = m[15] + m[12];
5491 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5492 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5493 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5494 r_refdef.view.frustum[2].dist = m[15] - m[13];
5496 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5497 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5498 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5499 r_refdef.view.frustum[3].dist = m[15] + m[13];
5501 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5502 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5503 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5504 r_refdef.view.frustum[4].dist = m[15] - m[14];
5506 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5507 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5508 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5509 r_refdef.view.frustum[5].dist = m[15] + m[14];
5512 if (r_refdef.view.useperspective)
5514 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5515 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5516 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5517 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5518 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5520 // then the normals from the corners relative to origin
5521 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5522 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5523 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5524 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5526 // in a NORMAL view, forward cross left == up
5527 // in a REFLECTED view, forward cross left == down
5528 // so our cross products above need to be adjusted for a left handed coordinate system
5529 CrossProduct(forward, left, v);
5530 if(DotProduct(v, up) < 0)
5532 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5533 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5534 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5535 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5538 // Leaving those out was a mistake, those were in the old code, and they
5539 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5540 // I couldn't reproduce it after adding those normalizations. --blub
5541 VectorNormalize(r_refdef.view.frustum[0].normal);
5542 VectorNormalize(r_refdef.view.frustum[1].normal);
5543 VectorNormalize(r_refdef.view.frustum[2].normal);
5544 VectorNormalize(r_refdef.view.frustum[3].normal);
5546 // make the corners absolute
5547 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5548 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5549 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5550 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5553 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5555 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5556 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5557 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5558 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5559 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5563 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5564 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5565 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5566 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5567 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5568 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5569 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5570 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5571 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5572 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5574 r_refdef.view.numfrustumplanes = 5;
5576 if (r_refdef.view.useclipplane)
5578 r_refdef.view.numfrustumplanes = 6;
5579 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5582 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5583 PlaneClassify(r_refdef.view.frustum + i);
5585 // LordHavoc: note to all quake engine coders, Quake had a special case
5586 // for 90 degrees which assumed a square view (wrong), so I removed it,
5587 // Quake2 has it disabled as well.
5589 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5590 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5591 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5592 //PlaneClassify(&frustum[0]);
5594 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5595 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5596 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5597 //PlaneClassify(&frustum[1]);
5599 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5600 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5601 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5602 //PlaneClassify(&frustum[2]);
5604 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5605 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5606 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5607 //PlaneClassify(&frustum[3]);
5610 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5611 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5612 //PlaneClassify(&frustum[4]);
5615 static void R_View_UpdateWithScissor(const int *myscissor)
5617 R_Main_ResizeViewCache();
5618 R_View_SetFrustum(myscissor);
5619 R_View_WorldVisibility(r_refdef.view.useclipplane);
5620 R_View_UpdateEntityVisible();
5621 R_View_UpdateEntityLighting();
5624 static void R_View_Update(void)
5626 R_Main_ResizeViewCache();
5627 R_View_SetFrustum(NULL);
5628 R_View_WorldVisibility(r_refdef.view.useclipplane);
5629 R_View_UpdateEntityVisible();
5630 R_View_UpdateEntityLighting();
5633 float viewscalefpsadjusted = 1.0f;
5635 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5637 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5638 scale = bound(0.03125f, scale, 1.0f);
5639 *outwidth = (int)ceil(width * scale);
5640 *outheight = (int)ceil(height * scale);
5643 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5645 const float *customclipplane = NULL;
5647 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5648 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5650 // LordHavoc: couldn't figure out how to make this approach the
5651 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5652 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5653 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5654 dist = r_refdef.view.clipplane.dist;
5655 plane[0] = r_refdef.view.clipplane.normal[0];
5656 plane[1] = r_refdef.view.clipplane.normal[1];
5657 plane[2] = r_refdef.view.clipplane.normal[2];
5659 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5662 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5663 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5665 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5666 if (!r_refdef.view.useperspective)
5667 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5668 else if (vid.stencil && r_useinfinitefarclip.integer)
5669 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5671 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5672 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5673 R_SetViewport(&r_refdef.view.viewport);
5674 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5676 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5677 float screenplane[4];
5678 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5679 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5680 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5681 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5682 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5686 void R_EntityMatrix(const matrix4x4_t *matrix)
5688 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5690 gl_modelmatrixchanged = false;
5691 gl_modelmatrix = *matrix;
5692 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5693 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5694 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5695 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5697 switch(vid.renderpath)
5699 case RENDERPATH_D3D9:
5701 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5702 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5705 case RENDERPATH_D3D10:
5706 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5708 case RENDERPATH_D3D11:
5709 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5711 case RENDERPATH_GL11:
5712 case RENDERPATH_GL13:
5713 case RENDERPATH_GLES1:
5715 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5718 case RENDERPATH_SOFT:
5719 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5720 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5722 case RENDERPATH_GL20:
5723 case RENDERPATH_GLES2:
5724 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5725 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5731 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5733 r_viewport_t viewport;
5737 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5738 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);
5739 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5740 R_SetViewport(&viewport);
5741 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5742 GL_Color(1, 1, 1, 1);
5743 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5744 GL_BlendFunc(GL_ONE, GL_ZERO);
5745 GL_ScissorTest(false);
5746 GL_DepthMask(false);
5747 GL_DepthRange(0, 1);
5748 GL_DepthTest(false);
5749 GL_DepthFunc(GL_LEQUAL);
5750 R_EntityMatrix(&identitymatrix);
5751 R_Mesh_ResetTextureState();
5752 GL_PolygonOffset(0, 0);
5753 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5754 switch(vid.renderpath)
5756 case RENDERPATH_GL11:
5757 case RENDERPATH_GL13:
5758 case RENDERPATH_GL20:
5759 case RENDERPATH_GLES1:
5760 case RENDERPATH_GLES2:
5761 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5763 case RENDERPATH_D3D9:
5764 case RENDERPATH_D3D10:
5765 case RENDERPATH_D3D11:
5766 case RENDERPATH_SOFT:
5769 GL_CullFace(GL_NONE);
5774 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5778 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5781 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5785 R_SetupView(true, fbo, depthtexture, colortexture);
5786 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5787 GL_Color(1, 1, 1, 1);
5788 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5789 GL_BlendFunc(GL_ONE, GL_ZERO);
5790 GL_ScissorTest(true);
5792 GL_DepthRange(0, 1);
5794 GL_DepthFunc(GL_LEQUAL);
5795 R_EntityMatrix(&identitymatrix);
5796 R_Mesh_ResetTextureState();
5797 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5798 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5799 switch(vid.renderpath)
5801 case RENDERPATH_GL11:
5802 case RENDERPATH_GL13:
5803 case RENDERPATH_GL20:
5804 case RENDERPATH_GLES1:
5805 case RENDERPATH_GLES2:
5806 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5808 case RENDERPATH_D3D9:
5809 case RENDERPATH_D3D10:
5810 case RENDERPATH_D3D11:
5811 case RENDERPATH_SOFT:
5814 GL_CullFace(r_refdef.view.cullface_back);
5819 R_RenderView_UpdateViewVectors
5822 void R_RenderView_UpdateViewVectors(void)
5824 // break apart the view matrix into vectors for various purposes
5825 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5826 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5827 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5828 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5829 // make an inverted copy of the view matrix for tracking sprites
5830 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5833 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5834 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5836 static void R_Water_StartFrame(void)
5839 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5840 r_waterstate_waterplane_t *p;
5841 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;
5843 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5846 switch(vid.renderpath)
5848 case RENDERPATH_GL20:
5849 case RENDERPATH_D3D9:
5850 case RENDERPATH_D3D10:
5851 case RENDERPATH_D3D11:
5852 case RENDERPATH_SOFT:
5853 case RENDERPATH_GLES2:
5855 case RENDERPATH_GL11:
5856 case RENDERPATH_GL13:
5857 case RENDERPATH_GLES1:
5861 // set waterwidth and waterheight to the water resolution that will be
5862 // used (often less than the screen resolution for faster rendering)
5863 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5865 // calculate desired texture sizes
5866 // can't use water if the card does not support the texture size
5867 if (!r_water.integer || r_showsurfaces.integer)
5868 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5869 else if (vid.support.arb_texture_non_power_of_two)
5871 texturewidth = waterwidth;
5872 textureheight = waterheight;
5873 camerawidth = waterwidth;
5874 cameraheight = waterheight;
5878 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5879 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5880 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5881 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5884 // allocate textures as needed
5885 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))
5887 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5888 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5890 if (p->texture_refraction)
5891 R_FreeTexture(p->texture_refraction);
5892 p->texture_refraction = NULL;
5893 if (p->fbo_refraction)
5894 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5895 p->fbo_refraction = 0;
5896 if (p->texture_reflection)
5897 R_FreeTexture(p->texture_reflection);
5898 p->texture_reflection = NULL;
5899 if (p->fbo_reflection)
5900 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5901 p->fbo_reflection = 0;
5902 if (p->texture_camera)
5903 R_FreeTexture(p->texture_camera);
5904 p->texture_camera = NULL;
5906 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5909 memset(&r_fb.water, 0, sizeof(r_fb.water));
5910 r_fb.water.texturewidth = texturewidth;
5911 r_fb.water.textureheight = textureheight;
5912 r_fb.water.camerawidth = camerawidth;
5913 r_fb.water.cameraheight = cameraheight;
5916 if (r_fb.water.texturewidth)
5918 int scaledwidth, scaledheight;
5920 r_fb.water.enabled = true;
5922 // water resolution is usually reduced
5923 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5924 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5925 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5927 // set up variables that will be used in shader setup
5928 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5929 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5930 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5931 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5934 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5935 r_fb.water.numwaterplanes = 0;
5938 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5940 int planeindex, bestplaneindex, vertexindex;
5941 vec3_t mins, maxs, normal, center, v, n;
5942 vec_t planescore, bestplanescore;
5944 r_waterstate_waterplane_t *p;
5945 texture_t *t = R_GetCurrentTexture(surface->texture);
5947 rsurface.texture = t;
5948 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5949 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5950 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5952 // average the vertex normals, find the surface bounds (after deformvertexes)
5953 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5954 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5955 VectorCopy(n, normal);
5956 VectorCopy(v, mins);
5957 VectorCopy(v, maxs);
5958 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5960 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5961 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5962 VectorAdd(normal, n, normal);
5963 mins[0] = min(mins[0], v[0]);
5964 mins[1] = min(mins[1], v[1]);
5965 mins[2] = min(mins[2], v[2]);
5966 maxs[0] = max(maxs[0], v[0]);
5967 maxs[1] = max(maxs[1], v[1]);
5968 maxs[2] = max(maxs[2], v[2]);
5970 VectorNormalize(normal);
5971 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5973 VectorCopy(normal, plane.normal);
5974 VectorNormalize(plane.normal);
5975 plane.dist = DotProduct(center, plane.normal);
5976 PlaneClassify(&plane);
5977 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5979 // skip backfaces (except if nocullface is set)
5980 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5982 VectorNegate(plane.normal, plane.normal);
5984 PlaneClassify(&plane);
5988 // find a matching plane if there is one
5989 bestplaneindex = -1;
5990 bestplanescore = 1048576.0f;
5991 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5993 if(p->camera_entity == t->camera_entity)
5995 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5996 if (bestplaneindex < 0 || bestplanescore > planescore)
5998 bestplaneindex = planeindex;
5999 bestplanescore = planescore;
6003 planeindex = bestplaneindex;
6004 p = r_fb.water.waterplanes + planeindex;
6006 // if this surface does not fit any known plane rendered this frame, add one
6007 if (planeindex < 0 || bestplanescore > 0.001f)
6009 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6011 // store the new plane
6012 planeindex = r_fb.water.numwaterplanes++;
6013 p = r_fb.water.waterplanes + planeindex;
6015 // clear materialflags and pvs
6016 p->materialflags = 0;
6017 p->pvsvalid = false;
6018 p->camera_entity = t->camera_entity;
6019 VectorCopy(mins, p->mins);
6020 VectorCopy(maxs, p->maxs);
6024 // We're totally screwed.
6030 // merge mins/maxs when we're adding this surface to the plane
6031 p->mins[0] = min(p->mins[0], mins[0]);
6032 p->mins[1] = min(p->mins[1], mins[1]);
6033 p->mins[2] = min(p->mins[2], mins[2]);
6034 p->maxs[0] = max(p->maxs[0], maxs[0]);
6035 p->maxs[1] = max(p->maxs[1], maxs[1]);
6036 p->maxs[2] = max(p->maxs[2], maxs[2]);
6038 // merge this surface's materialflags into the waterplane
6039 p->materialflags |= t->currentmaterialflags;
6040 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6042 // merge this surface's PVS into the waterplane
6043 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6044 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6046 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6052 extern cvar_t r_drawparticles;
6053 extern cvar_t r_drawdecals;
6055 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6058 r_refdef_view_t originalview;
6059 r_refdef_view_t myview;
6060 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;
6061 r_waterstate_waterplane_t *p;
6063 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;
6066 originalview = r_refdef.view;
6068 // lowquality hack, temporarily shut down some cvars and restore afterwards
6069 qualityreduction = r_water_lowquality.integer;
6070 if (qualityreduction > 0)
6072 if (qualityreduction >= 1)
6074 old_r_shadows = r_shadows.integer;
6075 old_r_worldrtlight = r_shadow_realtime_world.integer;
6076 old_r_dlight = r_shadow_realtime_dlight.integer;
6077 Cvar_SetValueQuick(&r_shadows, 0);
6078 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6079 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6081 if (qualityreduction >= 2)
6083 old_r_dynamic = r_dynamic.integer;
6084 old_r_particles = r_drawparticles.integer;
6085 old_r_decals = r_drawdecals.integer;
6086 Cvar_SetValueQuick(&r_dynamic, 0);
6087 Cvar_SetValueQuick(&r_drawparticles, 0);
6088 Cvar_SetValueQuick(&r_drawdecals, 0);
6092 // make sure enough textures are allocated
6093 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6095 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6097 if (!p->texture_refraction)
6098 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);
6099 if (!p->texture_refraction)
6103 if (r_fb.water.depthtexture == NULL)
6104 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6105 if (p->fbo_refraction == 0)
6106 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6109 else if (p->materialflags & MATERIALFLAG_CAMERA)
6111 if (!p->texture_camera)
6112 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);
6113 if (!p->texture_camera)
6117 if (r_fb.water.depthtexture == NULL)
6118 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6119 if (p->fbo_camera == 0)
6120 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6124 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6126 if (!p->texture_reflection)
6127 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);
6128 if (!p->texture_reflection)
6132 if (r_fb.water.depthtexture == NULL)
6133 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6134 if (p->fbo_reflection == 0)
6135 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6141 r_refdef.view = originalview;
6142 r_refdef.view.showdebug = false;
6143 r_refdef.view.width = r_fb.water.waterwidth;
6144 r_refdef.view.height = r_fb.water.waterheight;
6145 r_refdef.view.useclipplane = true;
6146 myview = r_refdef.view;
6147 r_fb.water.renderingscene = true;
6148 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6150 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6152 r_refdef.view = myview;
6153 if(r_water_scissormode.integer)
6155 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6156 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6157 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6160 // render reflected scene and copy into texture
6161 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6162 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6163 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6164 r_refdef.view.clipplane = p->plane;
6165 // reverse the cullface settings for this render
6166 r_refdef.view.cullface_front = GL_FRONT;
6167 r_refdef.view.cullface_back = GL_BACK;
6168 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6170 r_refdef.view.usecustompvs = true;
6172 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6174 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6177 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6178 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6179 R_ClearScreen(r_refdef.fogenabled);
6180 if(r_water_scissormode.integer & 2)
6181 R_View_UpdateWithScissor(myscissor);
6184 R_AnimCache_CacheVisibleEntities();
6185 if(r_water_scissormode.integer & 1)
6186 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6187 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6189 if (!p->fbo_reflection)
6190 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);
6191 r_fb.water.hideplayer = false;
6194 // render the normal view scene and copy into texture
6195 // (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)
6196 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6198 r_refdef.view = myview;
6199 if(r_water_scissormode.integer)
6201 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6202 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6203 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6206 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6208 r_refdef.view.clipplane = p->plane;
6209 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6210 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6212 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6214 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6215 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6216 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6217 R_RenderView_UpdateViewVectors();
6218 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6220 r_refdef.view.usecustompvs = true;
6221 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);
6225 PlaneClassify(&r_refdef.view.clipplane);
6227 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6228 R_ClearScreen(r_refdef.fogenabled);
6229 if(r_water_scissormode.integer & 2)
6230 R_View_UpdateWithScissor(myscissor);
6233 R_AnimCache_CacheVisibleEntities();
6234 if(r_water_scissormode.integer & 1)
6235 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6236 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6238 if (!p->fbo_refraction)
6239 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);
6240 r_fb.water.hideplayer = false;
6242 else if (p->materialflags & MATERIALFLAG_CAMERA)
6244 r_refdef.view = myview;
6246 r_refdef.view.clipplane = p->plane;
6247 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6248 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6250 r_refdef.view.width = r_fb.water.camerawidth;
6251 r_refdef.view.height = r_fb.water.cameraheight;
6252 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6253 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6254 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6255 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6257 if(p->camera_entity)
6259 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6260 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6263 // note: all of the view is used for displaying... so
6264 // there is no use in scissoring
6266 // reverse the cullface settings for this render
6267 r_refdef.view.cullface_front = GL_FRONT;
6268 r_refdef.view.cullface_back = GL_BACK;
6269 // also reverse the view matrix
6270 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
6271 R_RenderView_UpdateViewVectors();
6272 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6274 r_refdef.view.usecustompvs = true;
6275 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);
6278 // camera needs no clipplane
6279 r_refdef.view.useclipplane = false;
6281 PlaneClassify(&r_refdef.view.clipplane);
6283 r_fb.water.hideplayer = false;
6285 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6286 R_ClearScreen(r_refdef.fogenabled);
6288 R_AnimCache_CacheVisibleEntities();
6289 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6292 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);
6293 r_fb.water.hideplayer = false;
6297 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6298 r_fb.water.renderingscene = false;
6299 r_refdef.view = originalview;
6300 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6301 if (!r_fb.water.depthtexture)
6302 R_ClearScreen(r_refdef.fogenabled);
6304 R_AnimCache_CacheVisibleEntities();
6307 r_refdef.view = originalview;
6308 r_fb.water.renderingscene = false;
6309 Cvar_SetValueQuick(&r_water, 0);
6310 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6312 // lowquality hack, restore cvars
6313 if (qualityreduction > 0)
6315 if (qualityreduction >= 1)
6317 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6318 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6319 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6321 if (qualityreduction >= 2)
6323 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6324 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6325 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6330 static void R_Bloom_StartFrame(void)
6333 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6334 int viewwidth, viewheight;
6335 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6336 textype_t textype = TEXTYPE_COLORBUFFER;
6338 switch (vid.renderpath)
6340 case RENDERPATH_GL20:
6341 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6342 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6344 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6345 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6348 case RENDERPATH_GL11:
6349 case RENDERPATH_GL13:
6350 case RENDERPATH_GLES1:
6351 case RENDERPATH_GLES2:
6352 case RENDERPATH_D3D9:
6353 case RENDERPATH_D3D10:
6354 case RENDERPATH_D3D11:
6355 r_fb.usedepthtextures = false;
6357 case RENDERPATH_SOFT:
6358 r_fb.usedepthtextures = true;
6362 if (r_viewscale_fpsscaling.integer)
6364 double actualframetime;
6365 double targetframetime;
6367 actualframetime = r_refdef.lastdrawscreentime;
6368 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6369 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6370 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6371 if (r_viewscale_fpsscaling_stepsize.value > 0)
6372 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6373 viewscalefpsadjusted += adjust;
6374 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6377 viewscalefpsadjusted = 1.0f;
6379 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6381 switch(vid.renderpath)
6383 case RENDERPATH_GL20:
6384 case RENDERPATH_D3D9:
6385 case RENDERPATH_D3D10:
6386 case RENDERPATH_D3D11:
6387 case RENDERPATH_SOFT:
6388 case RENDERPATH_GLES2:
6390 case RENDERPATH_GL11:
6391 case RENDERPATH_GL13:
6392 case RENDERPATH_GLES1:
6396 // set bloomwidth and bloomheight to the bloom resolution that will be
6397 // used (often less than the screen resolution for faster rendering)
6398 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6399 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6400 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6401 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6402 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6404 // calculate desired texture sizes
6405 if (vid.support.arb_texture_non_power_of_two)
6407 screentexturewidth = vid.width;
6408 screentextureheight = vid.height;
6409 bloomtexturewidth = r_fb.bloomwidth;
6410 bloomtextureheight = r_fb.bloomheight;
6414 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6415 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6416 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6417 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6420 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))
6422 Cvar_SetValueQuick(&r_bloom, 0);
6423 Cvar_SetValueQuick(&r_motionblur, 0);
6424 Cvar_SetValueQuick(&r_damageblur, 0);
6427 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6429 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6431 && r_viewscale.value == 1.0f
6432 && !r_viewscale_fpsscaling.integer)
6433 screentexturewidth = screentextureheight = 0;
6434 if (!r_bloom.integer)
6435 bloomtexturewidth = bloomtextureheight = 0;
6437 // allocate textures as needed
6438 if (r_fb.screentexturewidth != screentexturewidth
6439 || r_fb.screentextureheight != screentextureheight
6440 || r_fb.bloomtexturewidth != bloomtexturewidth
6441 || r_fb.bloomtextureheight != bloomtextureheight
6442 || r_fb.textype != textype
6443 || useviewfbo != (r_fb.fbo != 0))
6445 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6447 if (r_fb.bloomtexture[i])
6448 R_FreeTexture(r_fb.bloomtexture[i]);
6449 r_fb.bloomtexture[i] = NULL;
6451 if (r_fb.bloomfbo[i])
6452 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6453 r_fb.bloomfbo[i] = 0;
6457 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6460 if (r_fb.colortexture)
6461 R_FreeTexture(r_fb.colortexture);
6462 r_fb.colortexture = NULL;
6464 if (r_fb.depthtexture)
6465 R_FreeTexture(r_fb.depthtexture);
6466 r_fb.depthtexture = NULL;
6468 if (r_fb.ghosttexture)
6469 R_FreeTexture(r_fb.ghosttexture);
6470 r_fb.ghosttexture = NULL;
6472 r_fb.screentexturewidth = screentexturewidth;
6473 r_fb.screentextureheight = screentextureheight;
6474 r_fb.bloomtexturewidth = bloomtexturewidth;
6475 r_fb.bloomtextureheight = bloomtextureheight;
6476 r_fb.textype = textype;
6478 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6480 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6481 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);
6482 r_fb.ghosttexture_valid = false;
6483 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);
6486 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6487 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6488 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6492 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6494 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6496 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);
6498 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6503 // bloom texture is a different resolution
6504 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6505 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6506 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6507 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6508 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6510 // set up a texcoord array for the full resolution screen image
6511 // (we have to keep this around to copy back during final render)
6512 r_fb.screentexcoord2f[0] = 0;
6513 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6514 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6515 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6516 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6517 r_fb.screentexcoord2f[5] = 0;
6518 r_fb.screentexcoord2f[6] = 0;
6519 r_fb.screentexcoord2f[7] = 0;
6523 for (i = 1;i < 8;i += 2)
6525 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6529 // set up a texcoord array for the reduced resolution bloom image
6530 // (which will be additive blended over the screen image)
6531 r_fb.bloomtexcoord2f[0] = 0;
6532 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6533 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6534 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6535 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6536 r_fb.bloomtexcoord2f[5] = 0;
6537 r_fb.bloomtexcoord2f[6] = 0;
6538 r_fb.bloomtexcoord2f[7] = 0;
6540 switch(vid.renderpath)
6542 case RENDERPATH_GL11:
6543 case RENDERPATH_GL13:
6544 case RENDERPATH_GL20:
6545 case RENDERPATH_SOFT:
6546 case RENDERPATH_GLES1:
6547 case RENDERPATH_GLES2:
6549 case RENDERPATH_D3D9:
6550 case RENDERPATH_D3D10:
6551 case RENDERPATH_D3D11:
6552 for (i = 0;i < 4;i++)
6554 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6555 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6556 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6557 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6562 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6565 r_refdef.view.clear = true;
6568 static void R_Bloom_MakeTexture(void)
6571 float xoffset, yoffset, r, brighten;
6573 float colorscale = r_bloom_colorscale.value;
6575 r_refdef.stats[r_stat_bloom]++;
6578 // this copy is unnecessary since it happens in R_BlendView already
6581 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);
6582 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6586 // scale down screen texture to the bloom texture size
6588 r_fb.bloomindex = 0;
6589 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6590 R_SetViewport(&r_fb.bloomviewport);
6591 GL_DepthTest(false);
6592 GL_BlendFunc(GL_ONE, GL_ZERO);
6593 GL_Color(colorscale, colorscale, colorscale, 1);
6594 // 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...
6595 switch(vid.renderpath)
6597 case RENDERPATH_GL11:
6598 case RENDERPATH_GL13:
6599 case RENDERPATH_GL20:
6600 case RENDERPATH_GLES1:
6601 case RENDERPATH_GLES2:
6602 case RENDERPATH_SOFT:
6603 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6605 case RENDERPATH_D3D9:
6606 case RENDERPATH_D3D10:
6607 case RENDERPATH_D3D11:
6608 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6611 // TODO: do boxfilter scale-down in shader?
6612 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6613 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6614 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6616 // we now have a properly scaled bloom image
6617 if (!r_fb.bloomfbo[r_fb.bloomindex])
6619 // copy it into the bloom texture
6620 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);
6621 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6624 // multiply bloom image by itself as many times as desired
6625 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6627 intex = r_fb.bloomtexture[r_fb.bloomindex];
6628 r_fb.bloomindex ^= 1;
6629 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6631 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6632 if (!r_fb.bloomfbo[r_fb.bloomindex])
6634 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6635 GL_Color(r,r,r,1); // apply fix factor
6640 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6641 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6642 GL_Color(1,1,1,1); // no fix factor supported here
6644 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6645 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6646 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6647 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6649 if (!r_fb.bloomfbo[r_fb.bloomindex])
6651 // copy the darkened image to a texture
6652 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);
6653 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6657 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6658 brighten = r_bloom_brighten.value;
6659 brighten = sqrt(brighten);
6661 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6663 for (dir = 0;dir < 2;dir++)
6665 intex = r_fb.bloomtexture[r_fb.bloomindex];
6666 r_fb.bloomindex ^= 1;
6667 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6668 // blend on at multiple vertical offsets to achieve a vertical blur
6669 // TODO: do offset blends using GLSL
6670 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6671 GL_BlendFunc(GL_ONE, GL_ZERO);
6672 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6673 for (x = -range;x <= range;x++)
6675 if (!dir){xoffset = 0;yoffset = x;}
6676 else {xoffset = x;yoffset = 0;}
6677 xoffset /= (float)r_fb.bloomtexturewidth;
6678 yoffset /= (float)r_fb.bloomtextureheight;
6679 // compute a texcoord array with the specified x and y offset
6680 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6681 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6682 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6683 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6684 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6685 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6686 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6687 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6688 // this r value looks like a 'dot' particle, fading sharply to
6689 // black at the edges
6690 // (probably not realistic but looks good enough)
6691 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6692 //r = brighten/(range*2+1);
6693 r = brighten / (range * 2 + 1);
6695 r *= (1 - x*x/(float)(range*range));
6696 GL_Color(r, r, r, 1);
6697 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6698 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6699 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6700 GL_BlendFunc(GL_ONE, GL_ONE);
6703 if (!r_fb.bloomfbo[r_fb.bloomindex])
6705 // copy the vertically or horizontally blurred bloom view to a texture
6706 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);
6707 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6712 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6714 unsigned int permutation;
6715 float uservecs[4][4];
6717 R_EntityMatrix(&identitymatrix);
6719 switch (vid.renderpath)
6721 case RENDERPATH_GL20:
6722 case RENDERPATH_D3D9:
6723 case RENDERPATH_D3D10:
6724 case RENDERPATH_D3D11:
6725 case RENDERPATH_SOFT:
6726 case RENDERPATH_GLES2:
6728 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6729 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6730 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6731 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6732 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6734 if (r_fb.colortexture)
6738 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);
6739 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6742 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6744 // declare variables
6745 float blur_factor, blur_mouseaccel, blur_velocity;
6746 static float blur_average;
6747 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6749 // set a goal for the factoring
6750 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6751 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6752 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6753 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6754 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6755 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6757 // from the goal, pick an averaged value between goal and last value
6758 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6759 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6761 // enforce minimum amount of blur
6762 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6764 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6766 // calculate values into a standard alpha
6767 cl.motionbluralpha = 1 - exp(-
6769 (r_motionblur.value * blur_factor / 80)
6771 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6774 max(0.0001, cl.time - cl.oldtime) // fps independent
6777 // randomization for the blur value to combat persistent ghosting
6778 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6779 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6782 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6783 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6785 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6786 GL_Color(1, 1, 1, cl.motionbluralpha);
6787 switch(vid.renderpath)
6789 case RENDERPATH_GL11:
6790 case RENDERPATH_GL13:
6791 case RENDERPATH_GL20:
6792 case RENDERPATH_GLES1:
6793 case RENDERPATH_GLES2:
6794 case RENDERPATH_SOFT:
6795 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6797 case RENDERPATH_D3D9:
6798 case RENDERPATH_D3D10:
6799 case RENDERPATH_D3D11:
6800 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6803 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6804 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6805 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6808 // updates old view angles for next pass
6809 VectorCopy(cl.viewangles, blur_oldangles);
6811 // copy view into the ghost texture
6812 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);
6813 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6814 r_fb.ghosttexture_valid = true;
6819 // no r_fb.colortexture means we're rendering to the real fb
6820 // we may still have to do view tint...
6821 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6823 // apply a color tint to the whole view
6824 R_ResetViewRendering2D(0, NULL, NULL);
6825 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6826 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6827 R_SetupShader_Generic_NoTexture(false, true);
6828 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6829 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6831 break; // no screen processing, no bloom, skip it
6834 if (r_fb.bloomtexture[0])
6836 // make the bloom texture
6837 R_Bloom_MakeTexture();
6840 #if _MSC_VER >= 1400
6841 #define sscanf sscanf_s
6843 memset(uservecs, 0, sizeof(uservecs));
6844 if (r_glsl_postprocess_uservec1_enable.integer)
6845 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6846 if (r_glsl_postprocess_uservec2_enable.integer)
6847 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6848 if (r_glsl_postprocess_uservec3_enable.integer)
6849 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6850 if (r_glsl_postprocess_uservec4_enable.integer)
6851 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6853 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6854 GL_Color(1, 1, 1, 1);
6855 GL_BlendFunc(GL_ONE, GL_ZERO);
6857 switch(vid.renderpath)
6859 case RENDERPATH_GL20:
6860 case RENDERPATH_GLES2:
6861 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6862 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6863 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6864 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6865 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6866 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]);
6867 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6868 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]);
6869 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]);
6870 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]);
6871 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]);
6872 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6873 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6874 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);
6876 case RENDERPATH_D3D9:
6878 // 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...
6879 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6880 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6881 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6882 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6883 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6884 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6885 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6886 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6887 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6888 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6889 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6890 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6891 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6892 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6895 case RENDERPATH_D3D10:
6896 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6898 case RENDERPATH_D3D11:
6899 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6901 case RENDERPATH_SOFT:
6902 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6903 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6904 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6905 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6906 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6907 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6908 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6909 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6910 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6911 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6912 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6913 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6914 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6915 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6920 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6921 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6923 case RENDERPATH_GL11:
6924 case RENDERPATH_GL13:
6925 case RENDERPATH_GLES1:
6926 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6928 // apply a color tint to the whole view
6929 R_ResetViewRendering2D(0, NULL, NULL);
6930 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6931 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6932 R_SetupShader_Generic_NoTexture(false, true);
6933 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6934 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6940 matrix4x4_t r_waterscrollmatrix;
6942 void R_UpdateFog(void)
6945 if (gamemode == GAME_NEHAHRA)
6947 if (gl_fogenable.integer)
6949 r_refdef.oldgl_fogenable = true;
6950 r_refdef.fog_density = gl_fogdensity.value;
6951 r_refdef.fog_red = gl_fogred.value;
6952 r_refdef.fog_green = gl_foggreen.value;
6953 r_refdef.fog_blue = gl_fogblue.value;
6954 r_refdef.fog_alpha = 1;
6955 r_refdef.fog_start = 0;
6956 r_refdef.fog_end = gl_skyclip.value;
6957 r_refdef.fog_height = 1<<30;
6958 r_refdef.fog_fadedepth = 128;
6960 else if (r_refdef.oldgl_fogenable)
6962 r_refdef.oldgl_fogenable = false;
6963 r_refdef.fog_density = 0;
6964 r_refdef.fog_red = 0;
6965 r_refdef.fog_green = 0;
6966 r_refdef.fog_blue = 0;
6967 r_refdef.fog_alpha = 0;
6968 r_refdef.fog_start = 0;
6969 r_refdef.fog_end = 0;
6970 r_refdef.fog_height = 1<<30;
6971 r_refdef.fog_fadedepth = 128;
6976 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6977 r_refdef.fog_start = max(0, r_refdef.fog_start);
6978 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6980 if (r_refdef.fog_density && r_drawfog.integer)
6982 r_refdef.fogenabled = true;
6983 // this is the point where the fog reaches 0.9986 alpha, which we
6984 // consider a good enough cutoff point for the texture
6985 // (0.9986 * 256 == 255.6)
6986 if (r_fog_exp2.integer)
6987 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6989 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6990 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6991 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6992 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6993 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6994 R_BuildFogHeightTexture();
6995 // fog color was already set
6996 // update the fog texture
6997 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)
6998 R_BuildFogTexture();
6999 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7000 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7003 r_refdef.fogenabled = false;
7006 if (r_refdef.fog_density)
7008 r_refdef.fogcolor[0] = r_refdef.fog_red;
7009 r_refdef.fogcolor[1] = r_refdef.fog_green;
7010 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7012 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7013 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7014 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7015 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7019 VectorCopy(r_refdef.fogcolor, fogvec);
7020 // color.rgb *= ContrastBoost * SceneBrightness;
7021 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7022 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7023 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7024 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7029 void R_UpdateVariables(void)
7033 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7035 r_refdef.farclip = r_farclip_base.value;
7036 if (r_refdef.scene.worldmodel)
7037 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7038 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7040 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7041 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7042 r_refdef.polygonfactor = 0;
7043 r_refdef.polygonoffset = 0;
7044 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7045 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7047 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7048 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7049 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7050 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7051 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7052 if (FAKELIGHT_ENABLED)
7054 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7056 else if (r_refdef.scene.worldmodel)
7058 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7060 if (r_showsurfaces.integer)
7062 r_refdef.scene.rtworld = false;
7063 r_refdef.scene.rtworldshadows = false;
7064 r_refdef.scene.rtdlight = false;
7065 r_refdef.scene.rtdlightshadows = false;
7066 r_refdef.lightmapintensity = 0;
7069 r_gpuskeletal = false;
7070 switch(vid.renderpath)
7072 case RENDERPATH_GL20:
7073 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7074 case RENDERPATH_D3D9:
7075 case RENDERPATH_D3D10:
7076 case RENDERPATH_D3D11:
7077 case RENDERPATH_SOFT:
7078 case RENDERPATH_GLES2:
7079 if(v_glslgamma.integer && !vid_gammatables_trivial)
7081 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7083 // build GLSL gamma texture
7084 #define RAMPWIDTH 256
7085 unsigned short ramp[RAMPWIDTH * 3];
7086 unsigned char rampbgr[RAMPWIDTH][4];
7089 r_texture_gammaramps_serial = vid_gammatables_serial;
7091 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7092 for(i = 0; i < RAMPWIDTH; ++i)
7094 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7095 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7096 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7099 if (r_texture_gammaramps)
7101 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7105 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7111 // remove GLSL gamma texture
7114 case RENDERPATH_GL11:
7115 case RENDERPATH_GL13:
7116 case RENDERPATH_GLES1:
7121 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7122 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7128 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7129 if( scenetype != r_currentscenetype ) {
7130 // store the old scenetype
7131 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7132 r_currentscenetype = scenetype;
7133 // move in the new scene
7134 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7143 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7145 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7146 if( scenetype == r_currentscenetype ) {
7147 return &r_refdef.scene;
7149 return &r_scenes_store[ scenetype ];
7153 static int R_SortEntities_Compare(const void *ap, const void *bp)
7155 const entity_render_t *a = *(const entity_render_t **)ap;
7156 const entity_render_t *b = *(const entity_render_t **)bp;
7159 if(a->model < b->model)
7161 if(a->model > b->model)
7165 // TODO possibly calculate the REAL skinnum here first using
7167 if(a->skinnum < b->skinnum)
7169 if(a->skinnum > b->skinnum)
7172 // everything we compared is equal
7175 static void R_SortEntities(void)
7177 // below or equal 2 ents, sorting never gains anything
7178 if(r_refdef.scene.numentities <= 2)
7181 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7189 int dpsoftrast_test;
7190 extern cvar_t r_shadow_bouncegrid;
7191 void R_RenderView(void)
7193 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7195 rtexture_t *depthtexture;
7196 rtexture_t *colortexture;
7198 dpsoftrast_test = r_test.integer;
7200 if (r_timereport_active)
7201 R_TimeReport("start");
7202 r_textureframe++; // used only by R_GetCurrentTexture
7203 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7205 if(R_CompileShader_CheckStaticParms())
7208 if (!r_drawentities.integer)
7209 r_refdef.scene.numentities = 0;
7210 else if (r_sortentities.integer)
7213 R_AnimCache_ClearCache();
7215 /* adjust for stereo display */
7216 if(R_Stereo_Active())
7218 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);
7219 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7222 if (r_refdef.view.isoverlay)
7224 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7225 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7226 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7227 R_TimeReport("depthclear");
7229 r_refdef.view.showdebug = false;
7231 r_fb.water.enabled = false;
7232 r_fb.water.numwaterplanes = 0;
7234 R_RenderScene(0, NULL, NULL);
7236 r_refdef.view.matrix = originalmatrix;
7242 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7244 r_refdef.view.matrix = originalmatrix;
7248 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7250 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7251 // in sRGB fallback, behave similar to true sRGB: convert this
7252 // value from linear to sRGB
7253 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7255 R_RenderView_UpdateViewVectors();
7257 R_Shadow_UpdateWorldLightSelection();
7259 R_Bloom_StartFrame();
7261 // apply bloom brightness offset
7262 if(r_fb.bloomtexture[0])
7263 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7265 R_Water_StartFrame();
7267 // now we probably have an fbo to render into
7269 depthtexture = r_fb.depthtexture;
7270 colortexture = r_fb.colortexture;
7273 if (r_timereport_active)
7274 R_TimeReport("viewsetup");
7276 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7278 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7280 R_ClearScreen(r_refdef.fogenabled);
7281 if (r_timereport_active)
7282 R_TimeReport("viewclear");
7284 r_refdef.view.clear = true;
7286 r_refdef.view.showdebug = true;
7289 if (r_timereport_active)
7290 R_TimeReport("visibility");
7292 R_AnimCache_CacheVisibleEntities();
7293 if (r_timereport_active)
7294 R_TimeReport("animcache");
7296 R_Shadow_UpdateBounceGridTexture();
7297 if (r_timereport_active && r_shadow_bouncegrid.integer)
7298 R_TimeReport("bouncegrid");
7300 r_fb.water.numwaterplanes = 0;
7301 if (r_fb.water.enabled)
7302 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7304 R_RenderScene(fbo, depthtexture, colortexture);
7305 r_fb.water.numwaterplanes = 0;
7307 R_BlendView(fbo, depthtexture, colortexture);
7308 if (r_timereport_active)
7309 R_TimeReport("blendview");
7311 GL_Scissor(0, 0, vid.width, vid.height);
7312 GL_ScissorTest(false);
7314 r_refdef.view.matrix = originalmatrix;
7319 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7321 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7323 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7324 if (r_timereport_active)
7325 R_TimeReport("waterworld");
7328 // don't let sound skip if going slow
7329 if (r_refdef.scene.extraupdate)
7332 R_DrawModelsAddWaterPlanes();
7333 if (r_timereport_active)
7334 R_TimeReport("watermodels");
7336 if (r_fb.water.numwaterplanes)
7338 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7339 if (r_timereport_active)
7340 R_TimeReport("waterscenes");
7344 extern cvar_t cl_locs_show;
7345 static void R_DrawLocs(void);
7346 static void R_DrawEntityBBoxes(void);
7347 static void R_DrawModelDecals(void);
7348 extern cvar_t cl_decals_newsystem;
7349 extern qboolean r_shadow_usingdeferredprepass;
7350 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7352 qboolean shadowmapping = false;
7354 if (r_timereport_active)
7355 R_TimeReport("beginscene");
7357 r_refdef.stats[r_stat_renders]++;
7361 // don't let sound skip if going slow
7362 if (r_refdef.scene.extraupdate)
7365 R_MeshQueue_BeginScene();
7369 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);
7371 if (r_timereport_active)
7372 R_TimeReport("skystartframe");
7374 if (cl.csqc_vidvars.drawworld)
7376 // don't let sound skip if going slow
7377 if (r_refdef.scene.extraupdate)
7380 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7382 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7383 if (r_timereport_active)
7384 R_TimeReport("worldsky");
7387 if (R_DrawBrushModelsSky() && r_timereport_active)
7388 R_TimeReport("bmodelsky");
7390 if (skyrendermasked && skyrenderlater)
7392 // we have to force off the water clipping plane while rendering sky
7393 R_SetupView(false, fbo, depthtexture, colortexture);
7395 R_SetupView(true, fbo, depthtexture, colortexture);
7396 if (r_timereport_active)
7397 R_TimeReport("sky");
7401 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7402 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7403 R_Shadow_PrepareModelShadows();
7404 if (r_timereport_active)
7405 R_TimeReport("preparelights");
7407 if (R_Shadow_ShadowMappingEnabled())
7408 shadowmapping = true;
7410 if (r_shadow_usingdeferredprepass)
7411 R_Shadow_DrawPrepass();
7413 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7415 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7416 if (r_timereport_active)
7417 R_TimeReport("worlddepth");
7419 if (r_depthfirst.integer >= 2)
7421 R_DrawModelsDepth();
7422 if (r_timereport_active)
7423 R_TimeReport("modeldepth");
7426 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7428 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7429 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7430 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7431 // don't let sound skip if going slow
7432 if (r_refdef.scene.extraupdate)
7436 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7438 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7439 if (r_timereport_active)
7440 R_TimeReport("world");
7443 // don't let sound skip if going slow
7444 if (r_refdef.scene.extraupdate)
7448 if (r_timereport_active)
7449 R_TimeReport("models");
7451 // don't let sound skip if going slow
7452 if (r_refdef.scene.extraupdate)
7455 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7457 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7458 R_DrawModelShadows(fbo, depthtexture, colortexture);
7459 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7460 // don't let sound skip if going slow
7461 if (r_refdef.scene.extraupdate)
7465 if (!r_shadow_usingdeferredprepass)
7467 R_Shadow_DrawLights();
7468 if (r_timereport_active)
7469 R_TimeReport("rtlights");
7472 // don't let sound skip if going slow
7473 if (r_refdef.scene.extraupdate)
7476 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7478 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7479 R_DrawModelShadows(fbo, depthtexture, colortexture);
7480 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7481 // don't let sound skip if going slow
7482 if (r_refdef.scene.extraupdate)
7486 if (cl.csqc_vidvars.drawworld)
7488 if (cl_decals_newsystem.integer)
7490 R_DrawModelDecals();
7491 if (r_timereport_active)
7492 R_TimeReport("modeldecals");
7497 if (r_timereport_active)
7498 R_TimeReport("decals");
7502 if (r_timereport_active)
7503 R_TimeReport("particles");
7506 if (r_timereport_active)
7507 R_TimeReport("explosions");
7509 R_DrawLightningBeams();
7510 if (r_timereport_active)
7511 R_TimeReport("lightning");
7515 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7517 if (r_refdef.view.showdebug)
7519 if (cl_locs_show.integer)
7522 if (r_timereport_active)
7523 R_TimeReport("showlocs");
7526 if (r_drawportals.integer)
7529 if (r_timereport_active)
7530 R_TimeReport("portals");
7533 if (r_showbboxes.value > 0)
7535 R_DrawEntityBBoxes();
7536 if (r_timereport_active)
7537 R_TimeReport("bboxes");
7541 if (r_transparent.integer)
7543 R_MeshQueue_RenderTransparent();
7544 if (r_timereport_active)
7545 R_TimeReport("drawtrans");
7548 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))
7550 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7551 if (r_timereport_active)
7552 R_TimeReport("worlddebug");
7553 R_DrawModelsDebug();
7554 if (r_timereport_active)
7555 R_TimeReport("modeldebug");
7558 if (cl.csqc_vidvars.drawworld)
7560 R_Shadow_DrawCoronas();
7561 if (r_timereport_active)
7562 R_TimeReport("coronas");
7567 GL_DepthTest(false);
7568 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7569 GL_Color(1, 1, 1, 1);
7570 qglBegin(GL_POLYGON);
7571 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7572 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7573 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7574 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7576 qglBegin(GL_POLYGON);
7577 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]);
7578 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]);
7579 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]);
7580 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]);
7582 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7586 // don't let sound skip if going slow
7587 if (r_refdef.scene.extraupdate)
7591 static const unsigned short bboxelements[36] =
7601 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7604 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7606 RSurf_ActiveWorldEntity();
7608 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7609 GL_DepthMask(false);
7610 GL_DepthRange(0, 1);
7611 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7612 // R_Mesh_ResetTextureState();
7614 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7615 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7616 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7617 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7618 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7619 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7620 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7621 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7622 R_FillColors(color4f, 8, cr, cg, cb, ca);
7623 if (r_refdef.fogenabled)
7625 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7627 f1 = RSurf_FogVertex(v);
7629 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7630 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7631 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7634 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7635 R_Mesh_ResetTextureState();
7636 R_SetupShader_Generic_NoTexture(false, false);
7637 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7640 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7642 prvm_prog_t *prog = SVVM_prog;
7645 prvm_edict_t *edict;
7647 // this function draws bounding boxes of server entities
7651 GL_CullFace(GL_NONE);
7652 R_SetupShader_Generic_NoTexture(false, false);
7654 for (i = 0;i < numsurfaces;i++)
7656 edict = PRVM_EDICT_NUM(surfacelist[i]);
7657 switch ((int)PRVM_serveredictfloat(edict, solid))
7659 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7660 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7661 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7662 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7663 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7664 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7665 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7667 color[3] *= r_showbboxes.value;
7668 color[3] = bound(0, color[3], 1);
7669 GL_DepthTest(!r_showdisabledepthtest.integer);
7670 GL_CullFace(r_refdef.view.cullface_front);
7671 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7675 static void R_DrawEntityBBoxes(void)
7678 prvm_edict_t *edict;
7680 prvm_prog_t *prog = SVVM_prog;
7682 // this function draws bounding boxes of server entities
7686 for (i = 0;i < prog->num_edicts;i++)
7688 edict = PRVM_EDICT_NUM(i);
7689 if (edict->priv.server->free)
7691 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7692 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7694 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7696 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7697 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7701 static const int nomodelelement3i[24] =
7713 static const unsigned short nomodelelement3s[24] =
7725 static const float nomodelvertex3f[6*3] =
7735 static const float nomodelcolor4f[6*4] =
7737 0.0f, 0.0f, 0.5f, 1.0f,
7738 0.0f, 0.0f, 0.5f, 1.0f,
7739 0.0f, 0.5f, 0.0f, 1.0f,
7740 0.0f, 0.5f, 0.0f, 1.0f,
7741 0.5f, 0.0f, 0.0f, 1.0f,
7742 0.5f, 0.0f, 0.0f, 1.0f
7745 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7751 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);
7753 // this is only called once per entity so numsurfaces is always 1, and
7754 // surfacelist is always {0}, so this code does not handle batches
7756 if (rsurface.ent_flags & RENDER_ADDITIVE)
7758 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7759 GL_DepthMask(false);
7761 else if (rsurface.colormod[3] < 1)
7763 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7764 GL_DepthMask(false);
7768 GL_BlendFunc(GL_ONE, GL_ZERO);
7771 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7772 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7773 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7774 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7775 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7776 for (i = 0, c = color4f;i < 6;i++, c += 4)
7778 c[0] *= rsurface.colormod[0];
7779 c[1] *= rsurface.colormod[1];
7780 c[2] *= rsurface.colormod[2];
7781 c[3] *= rsurface.colormod[3];
7783 if (r_refdef.fogenabled)
7785 for (i = 0, c = color4f;i < 6;i++, c += 4)
7787 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7789 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7790 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7791 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7794 // R_Mesh_ResetTextureState();
7795 R_SetupShader_Generic_NoTexture(false, false);
7796 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7797 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7800 void R_DrawNoModel(entity_render_t *ent)
7803 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7804 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7805 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7807 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7810 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7812 vec3_t right1, right2, diff, normal;
7814 VectorSubtract (org2, org1, normal);
7816 // calculate 'right' vector for start
7817 VectorSubtract (r_refdef.view.origin, org1, diff);
7818 CrossProduct (normal, diff, right1);
7819 VectorNormalize (right1);
7821 // calculate 'right' vector for end
7822 VectorSubtract (r_refdef.view.origin, org2, diff);
7823 CrossProduct (normal, diff, right2);
7824 VectorNormalize (right2);
7826 vert[ 0] = org1[0] + width * right1[0];
7827 vert[ 1] = org1[1] + width * right1[1];
7828 vert[ 2] = org1[2] + width * right1[2];
7829 vert[ 3] = org1[0] - width * right1[0];
7830 vert[ 4] = org1[1] - width * right1[1];
7831 vert[ 5] = org1[2] - width * right1[2];
7832 vert[ 6] = org2[0] - width * right2[0];
7833 vert[ 7] = org2[1] - width * right2[1];
7834 vert[ 8] = org2[2] - width * right2[2];
7835 vert[ 9] = org2[0] + width * right2[0];
7836 vert[10] = org2[1] + width * right2[1];
7837 vert[11] = org2[2] + width * right2[2];
7840 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)
7842 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7843 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7844 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7845 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7846 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7847 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7848 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7849 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7850 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7851 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7852 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7853 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7856 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7861 VectorSet(v, x, y, z);
7862 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7863 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7865 if (i == mesh->numvertices)
7867 if (mesh->numvertices < mesh->maxvertices)
7869 VectorCopy(v, vertex3f);
7870 mesh->numvertices++;
7872 return mesh->numvertices;
7878 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7882 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7883 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7884 e = mesh->element3i + mesh->numtriangles * 3;
7885 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7887 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7888 if (mesh->numtriangles < mesh->maxtriangles)
7893 mesh->numtriangles++;
7895 element[1] = element[2];
7899 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7903 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7904 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7905 e = mesh->element3i + mesh->numtriangles * 3;
7906 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7908 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7909 if (mesh->numtriangles < mesh->maxtriangles)
7914 mesh->numtriangles++;
7916 element[1] = element[2];
7920 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7921 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7923 int planenum, planenum2;
7926 mplane_t *plane, *plane2;
7928 double temppoints[2][256*3];
7929 // figure out how large a bounding box we need to properly compute this brush
7931 for (w = 0;w < numplanes;w++)
7932 maxdist = max(maxdist, fabs(planes[w].dist));
7933 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7934 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7935 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7939 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7940 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7942 if (planenum2 == planenum)
7944 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);
7947 if (tempnumpoints < 3)
7949 // generate elements forming a triangle fan for this polygon
7950 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7954 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)
7956 texturelayer_t *layer;
7957 layer = t->currentlayers + t->currentnumlayers++;
7959 layer->depthmask = depthmask;
7960 layer->blendfunc1 = blendfunc1;
7961 layer->blendfunc2 = blendfunc2;
7962 layer->texture = texture;
7963 layer->texmatrix = *matrix;
7964 layer->color[0] = r;
7965 layer->color[1] = g;
7966 layer->color[2] = b;
7967 layer->color[3] = a;
7970 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7972 if(parms[0] == 0 && parms[1] == 0)
7974 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7975 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7980 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7983 index = parms[2] + rsurface.shadertime * parms[3];
7984 index -= floor(index);
7985 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7988 case Q3WAVEFUNC_NONE:
7989 case Q3WAVEFUNC_NOISE:
7990 case Q3WAVEFUNC_COUNT:
7993 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7994 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7995 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7996 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7997 case Q3WAVEFUNC_TRIANGLE:
7999 f = index - floor(index);
8012 f = parms[0] + parms[1] * f;
8013 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8014 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8018 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8025 matrix4x4_t matrix, temp;
8026 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8027 // it's better to have one huge fixup every 9 hours than gradual
8028 // degradation over time which looks consistently bad after many hours.
8030 // tcmod scroll in particular suffers from this degradation which can't be
8031 // effectively worked around even with floor() tricks because we don't
8032 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8033 // a workaround involving floor() would be incorrect anyway...
8034 shadertime = rsurface.shadertime;
8035 if (shadertime >= 32768.0f)
8036 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8037 switch(tcmod->tcmod)
8041 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8042 matrix = r_waterscrollmatrix;
8044 matrix = identitymatrix;
8046 case Q3TCMOD_ENTITYTRANSLATE:
8047 // this is used in Q3 to allow the gamecode to control texcoord
8048 // scrolling on the entity, which is not supported in darkplaces yet.
8049 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8051 case Q3TCMOD_ROTATE:
8052 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8053 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8054 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8057 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8059 case Q3TCMOD_SCROLL:
8060 // this particular tcmod is a "bug for bug" compatible one with regards to
8061 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8062 // specifically did the wrapping and so we must mimic that...
8063 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8064 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8065 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8067 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8068 w = (int) tcmod->parms[0];
8069 h = (int) tcmod->parms[1];
8070 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8072 idx = (int) floor(f * w * h);
8073 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8075 case Q3TCMOD_STRETCH:
8076 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8077 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8079 case Q3TCMOD_TRANSFORM:
8080 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8081 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8082 VectorSet(tcmat + 6, 0 , 0 , 1);
8083 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8084 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8086 case Q3TCMOD_TURBULENT:
8087 // this is handled in the RSurf_PrepareVertices function
8088 matrix = identitymatrix;
8092 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8095 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8097 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8098 char name[MAX_QPATH];
8099 skinframe_t *skinframe;
8100 unsigned char pixels[296*194];
8101 strlcpy(cache->name, skinname, sizeof(cache->name));
8102 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8103 if (developer_loading.integer)
8104 Con_Printf("loading %s\n", name);
8105 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8106 if (!skinframe || !skinframe->base)
8109 fs_offset_t filesize;
8111 f = FS_LoadFile(name, tempmempool, true, &filesize);
8114 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8115 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8119 cache->skinframe = skinframe;
8122 texture_t *R_GetCurrentTexture(texture_t *t)
8125 const entity_render_t *ent = rsurface.entity;
8126 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8127 q3shaderinfo_layer_tcmod_t *tcmod;
8129 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8130 return t->currentframe;
8131 t->update_lastrenderframe = r_textureframe;
8132 t->update_lastrenderentity = (void *)ent;
8134 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8135 t->camera_entity = ent->entitynumber;
8137 t->camera_entity = 0;
8139 // switch to an alternate material if this is a q1bsp animated material
8141 texture_t *texture = t;
8142 int s = rsurface.ent_skinnum;
8143 if ((unsigned int)s >= (unsigned int)model->numskins)
8145 if (model->skinscenes)
8147 if (model->skinscenes[s].framecount > 1)
8148 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8150 s = model->skinscenes[s].firstframe;
8153 t = t + s * model->num_surfaces;
8156 // use an alternate animation if the entity's frame is not 0,
8157 // and only if the texture has an alternate animation
8158 if (t->animated == 2) // q2bsp
8159 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8160 else if (rsurface.ent_alttextures && t->anim_total[1])
8161 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8163 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8165 texture->currentframe = t;
8168 // update currentskinframe to be a qw skin or animation frame
8169 if (rsurface.ent_qwskin >= 0)
8171 i = rsurface.ent_qwskin;
8172 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8174 r_qwskincache_size = cl.maxclients;
8176 Mem_Free(r_qwskincache);
8177 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8179 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8180 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8181 t->currentskinframe = r_qwskincache[i].skinframe;
8182 if (t->currentskinframe == NULL)
8183 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8185 else if (t->numskinframes >= 2)
8186 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8187 if (t->backgroundnumskinframes >= 2)
8188 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8190 t->currentmaterialflags = t->basematerialflags;
8191 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8192 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8193 t->currentalpha *= r_wateralpha.value;
8194 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8195 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8196 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8197 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8198 if (!(rsurface.ent_flags & RENDER_LIGHT))
8199 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8200 else if (FAKELIGHT_ENABLED)
8202 // no modellight if using fakelight for the map
8204 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8206 // pick a model lighting mode
8207 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8208 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8210 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8212 if (rsurface.ent_flags & RENDER_ADDITIVE)
8213 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8214 else if (t->currentalpha < 1)
8215 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8216 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8217 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8218 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8219 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8220 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8221 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8222 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8223 if (t->backgroundnumskinframes)
8224 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8225 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8227 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8228 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8231 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8232 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8234 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8235 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8237 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8238 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8240 // there is no tcmod
8241 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8243 t->currenttexmatrix = r_waterscrollmatrix;
8244 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8246 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8248 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8249 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8252 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8253 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8254 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8255 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8257 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8258 if (t->currentskinframe->qpixels)
8259 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8260 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8261 if (!t->basetexture)
8262 t->basetexture = r_texture_notexture;
8263 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8264 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8265 t->nmaptexture = t->currentskinframe->nmap;
8266 if (!t->nmaptexture)
8267 t->nmaptexture = r_texture_blanknormalmap;
8268 t->glosstexture = r_texture_black;
8269 t->glowtexture = t->currentskinframe->glow;
8270 t->fogtexture = t->currentskinframe->fog;
8271 t->reflectmasktexture = t->currentskinframe->reflect;
8272 if (t->backgroundnumskinframes)
8274 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8275 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8276 t->backgroundglosstexture = r_texture_black;
8277 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8278 if (!t->backgroundnmaptexture)
8279 t->backgroundnmaptexture = r_texture_blanknormalmap;
8280 // make sure that if glow is going to be used, both textures are not NULL
8281 if (!t->backgroundglowtexture && t->glowtexture)
8282 t->backgroundglowtexture = r_texture_black;
8283 if (!t->glowtexture && t->backgroundglowtexture)
8284 t->glowtexture = r_texture_black;
8288 t->backgroundbasetexture = r_texture_white;
8289 t->backgroundnmaptexture = r_texture_blanknormalmap;
8290 t->backgroundglosstexture = r_texture_black;
8291 t->backgroundglowtexture = NULL;
8293 t->specularpower = r_shadow_glossexponent.value;
8294 // TODO: store reference values for these in the texture?
8295 t->specularscale = 0;
8296 if (r_shadow_gloss.integer > 0)
8298 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8300 if (r_shadow_glossintensity.value > 0)
8302 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8303 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8304 t->specularscale = r_shadow_glossintensity.value;
8307 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8309 t->glosstexture = r_texture_white;
8310 t->backgroundglosstexture = r_texture_white;
8311 t->specularscale = r_shadow_gloss2intensity.value;
8312 t->specularpower = r_shadow_gloss2exponent.value;
8315 t->specularscale *= t->specularscalemod;
8316 t->specularpower *= t->specularpowermod;
8317 t->rtlightambient = 0;
8319 // lightmaps mode looks bad with dlights using actual texturing, so turn
8320 // off the colormap and glossmap, but leave the normalmap on as it still
8321 // accurately represents the shading involved
8322 if (gl_lightmaps.integer)
8324 t->basetexture = r_texture_grey128;
8325 t->pantstexture = r_texture_black;
8326 t->shirttexture = r_texture_black;
8327 if (gl_lightmaps.integer < 2)
8328 t->nmaptexture = r_texture_blanknormalmap;
8329 t->glosstexture = r_texture_black;
8330 t->glowtexture = NULL;
8331 t->fogtexture = NULL;
8332 t->reflectmasktexture = NULL;
8333 t->backgroundbasetexture = NULL;
8334 if (gl_lightmaps.integer < 2)
8335 t->backgroundnmaptexture = r_texture_blanknormalmap;
8336 t->backgroundglosstexture = r_texture_black;
8337 t->backgroundglowtexture = NULL;
8338 t->specularscale = 0;
8339 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8342 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8343 VectorClear(t->dlightcolor);
8344 t->currentnumlayers = 0;
8345 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8347 int blendfunc1, blendfunc2;
8349 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8351 blendfunc1 = GL_SRC_ALPHA;
8352 blendfunc2 = GL_ONE;
8354 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8356 blendfunc1 = GL_SRC_ALPHA;
8357 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8359 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8361 blendfunc1 = t->customblendfunc[0];
8362 blendfunc2 = t->customblendfunc[1];
8366 blendfunc1 = GL_ONE;
8367 blendfunc2 = GL_ZERO;
8369 // don't colormod evilblend textures
8370 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8371 VectorSet(t->lightmapcolor, 1, 1, 1);
8372 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8373 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8375 // fullbright is not affected by r_refdef.lightmapintensity
8376 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]);
8377 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8378 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]);
8379 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8380 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]);
8384 vec3_t ambientcolor;
8386 // set the color tint used for lights affecting this surface
8387 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8389 // q3bsp has no lightmap updates, so the lightstylevalue that
8390 // would normally be baked into the lightmap must be
8391 // applied to the color
8392 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8393 if (model->type == mod_brushq3)
8394 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8395 colorscale *= r_refdef.lightmapintensity;
8396 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8397 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8398 // basic lit geometry
8399 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]);
8400 // add pants/shirt if needed
8401 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8402 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]);
8403 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8404 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]);
8405 // now add ambient passes if needed
8406 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8408 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]);
8409 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8410 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]);
8411 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8412 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]);
8415 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8416 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]);
8417 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8419 // if this is opaque use alpha blend which will darken the earlier
8422 // if this is an alpha blended material, all the earlier passes
8423 // were darkened by fog already, so we only need to add the fog
8424 // color ontop through the fog mask texture
8426 // if this is an additive blended material, all the earlier passes
8427 // were darkened by fog already, and we should not add fog color
8428 // (because the background was not darkened, there is no fog color
8429 // that was lost behind it).
8430 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]);
8434 return t->currentframe;
8437 rsurfacestate_t rsurface;
8439 void RSurf_ActiveWorldEntity(void)
8441 dp_model_t *model = r_refdef.scene.worldmodel;
8442 //if (rsurface.entity == r_refdef.scene.worldentity)
8444 rsurface.entity = r_refdef.scene.worldentity;
8445 rsurface.skeleton = NULL;
8446 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8447 rsurface.ent_skinnum = 0;
8448 rsurface.ent_qwskin = -1;
8449 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8450 rsurface.shadertime = r_refdef.scene.time;
8451 rsurface.matrix = identitymatrix;
8452 rsurface.inversematrix = identitymatrix;
8453 rsurface.matrixscale = 1;
8454 rsurface.inversematrixscale = 1;
8455 R_EntityMatrix(&identitymatrix);
8456 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8457 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8458 rsurface.fograngerecip = r_refdef.fograngerecip;
8459 rsurface.fogheightfade = r_refdef.fogheightfade;
8460 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8461 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8462 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8463 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8464 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8465 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8466 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8467 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8468 rsurface.colormod[3] = 1;
8469 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);
8470 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8471 rsurface.frameblend[0].lerp = 1;
8472 rsurface.ent_alttextures = false;
8473 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8474 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8475 rsurface.entityskeletaltransform3x4 = NULL;
8476 rsurface.entityskeletaltransform3x4buffer = NULL;
8477 rsurface.entityskeletaltransform3x4offset = 0;
8478 rsurface.entityskeletaltransform3x4size = 0;;
8479 rsurface.entityskeletalnumtransforms = 0;
8480 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8481 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8482 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8483 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8484 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8485 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8486 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8487 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8488 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8489 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8490 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8491 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8492 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8493 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8494 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8495 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8496 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8497 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8498 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8499 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8500 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8501 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8502 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8503 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8504 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8505 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8506 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8507 rsurface.modelelement3i = model->surfmesh.data_element3i;
8508 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8509 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8510 rsurface.modelelement3s = model->surfmesh.data_element3s;
8511 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8512 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8513 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8514 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8515 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8516 rsurface.modelsurfaces = model->data_surfaces;
8517 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8518 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8519 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8520 rsurface.modelgeneratedvertex = false;
8521 rsurface.batchgeneratedvertex = false;
8522 rsurface.batchfirstvertex = 0;
8523 rsurface.batchnumvertices = 0;
8524 rsurface.batchfirsttriangle = 0;
8525 rsurface.batchnumtriangles = 0;
8526 rsurface.batchvertex3f = NULL;
8527 rsurface.batchvertex3f_vertexbuffer = NULL;
8528 rsurface.batchvertex3f_bufferoffset = 0;
8529 rsurface.batchsvector3f = NULL;
8530 rsurface.batchsvector3f_vertexbuffer = NULL;
8531 rsurface.batchsvector3f_bufferoffset = 0;
8532 rsurface.batchtvector3f = NULL;
8533 rsurface.batchtvector3f_vertexbuffer = NULL;
8534 rsurface.batchtvector3f_bufferoffset = 0;
8535 rsurface.batchnormal3f = NULL;
8536 rsurface.batchnormal3f_vertexbuffer = NULL;
8537 rsurface.batchnormal3f_bufferoffset = 0;
8538 rsurface.batchlightmapcolor4f = NULL;
8539 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8540 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8541 rsurface.batchtexcoordtexture2f = NULL;
8542 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8543 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8544 rsurface.batchtexcoordlightmap2f = NULL;
8545 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8546 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8547 rsurface.batchskeletalindex4ub = NULL;
8548 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8549 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8550 rsurface.batchskeletalweight4ub = NULL;
8551 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8552 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8553 rsurface.batchvertexmesh = NULL;
8554 rsurface.batchvertexmesh_vertexbuffer = NULL;
8555 rsurface.batchvertexmesh_bufferoffset = 0;
8556 rsurface.batchelement3i = NULL;
8557 rsurface.batchelement3i_indexbuffer = NULL;
8558 rsurface.batchelement3i_bufferoffset = 0;
8559 rsurface.batchelement3s = NULL;
8560 rsurface.batchelement3s_indexbuffer = NULL;
8561 rsurface.batchelement3s_bufferoffset = 0;
8562 rsurface.passcolor4f = NULL;
8563 rsurface.passcolor4f_vertexbuffer = NULL;
8564 rsurface.passcolor4f_bufferoffset = 0;
8565 rsurface.forcecurrenttextureupdate = false;
8568 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8570 dp_model_t *model = ent->model;
8571 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8573 rsurface.entity = (entity_render_t *)ent;
8574 rsurface.skeleton = ent->skeleton;
8575 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8576 rsurface.ent_skinnum = ent->skinnum;
8577 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;
8578 rsurface.ent_flags = ent->flags;
8579 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8580 rsurface.matrix = ent->matrix;
8581 rsurface.inversematrix = ent->inversematrix;
8582 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8583 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8584 R_EntityMatrix(&rsurface.matrix);
8585 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8586 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8587 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8588 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8589 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8590 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8591 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8592 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8593 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8594 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8595 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8596 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8597 rsurface.colormod[3] = ent->alpha;
8598 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8599 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8600 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8601 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8602 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8603 if (ent->model->brush.submodel && !prepass)
8605 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8606 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8608 // if the animcache code decided it should use the shader path, skip the deform step
8609 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8610 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8611 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8612 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8613 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8614 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8616 if (ent->animcache_vertex3f)
8618 r_refdef.stats[r_stat_batch_entitycache_count]++;
8619 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8620 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8621 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8622 rsurface.modelvertex3f = ent->animcache_vertex3f;
8623 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8624 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8625 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8626 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8627 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8628 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8629 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8630 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8631 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8632 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8633 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8634 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8635 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8636 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8638 else if (wanttangents)
8640 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8641 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8642 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8643 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8644 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8645 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8646 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8647 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8648 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8649 rsurface.modelvertexmesh = NULL;
8650 rsurface.modelvertexmesh_vertexbuffer = NULL;
8651 rsurface.modelvertexmesh_bufferoffset = 0;
8652 rsurface.modelvertex3f_vertexbuffer = NULL;
8653 rsurface.modelvertex3f_bufferoffset = 0;
8654 rsurface.modelvertex3f_vertexbuffer = 0;
8655 rsurface.modelvertex3f_bufferoffset = 0;
8656 rsurface.modelsvector3f_vertexbuffer = 0;
8657 rsurface.modelsvector3f_bufferoffset = 0;
8658 rsurface.modeltvector3f_vertexbuffer = 0;
8659 rsurface.modeltvector3f_bufferoffset = 0;
8660 rsurface.modelnormal3f_vertexbuffer = 0;
8661 rsurface.modelnormal3f_bufferoffset = 0;
8663 else if (wantnormals)
8665 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8666 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8667 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8668 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8669 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8670 rsurface.modelsvector3f = NULL;
8671 rsurface.modeltvector3f = NULL;
8672 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8673 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8674 rsurface.modelvertexmesh = NULL;
8675 rsurface.modelvertexmesh_vertexbuffer = NULL;
8676 rsurface.modelvertexmesh_bufferoffset = 0;
8677 rsurface.modelvertex3f_vertexbuffer = NULL;
8678 rsurface.modelvertex3f_bufferoffset = 0;
8679 rsurface.modelvertex3f_vertexbuffer = 0;
8680 rsurface.modelvertex3f_bufferoffset = 0;
8681 rsurface.modelsvector3f_vertexbuffer = 0;
8682 rsurface.modelsvector3f_bufferoffset = 0;
8683 rsurface.modeltvector3f_vertexbuffer = 0;
8684 rsurface.modeltvector3f_bufferoffset = 0;
8685 rsurface.modelnormal3f_vertexbuffer = 0;
8686 rsurface.modelnormal3f_bufferoffset = 0;
8690 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8691 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8692 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8693 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8694 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8695 rsurface.modelsvector3f = NULL;
8696 rsurface.modeltvector3f = NULL;
8697 rsurface.modelnormal3f = NULL;
8698 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8699 rsurface.modelvertexmesh = NULL;
8700 rsurface.modelvertexmesh_vertexbuffer = NULL;
8701 rsurface.modelvertexmesh_bufferoffset = 0;
8702 rsurface.modelvertex3f_vertexbuffer = NULL;
8703 rsurface.modelvertex3f_bufferoffset = 0;
8704 rsurface.modelvertex3f_vertexbuffer = 0;
8705 rsurface.modelvertex3f_bufferoffset = 0;
8706 rsurface.modelsvector3f_vertexbuffer = 0;
8707 rsurface.modelsvector3f_bufferoffset = 0;
8708 rsurface.modeltvector3f_vertexbuffer = 0;
8709 rsurface.modeltvector3f_bufferoffset = 0;
8710 rsurface.modelnormal3f_vertexbuffer = 0;
8711 rsurface.modelnormal3f_bufferoffset = 0;
8713 rsurface.modelgeneratedvertex = true;
8717 if (rsurface.entityskeletaltransform3x4)
8719 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8720 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8721 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8722 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8726 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8727 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8728 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8729 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8731 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8732 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8733 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8734 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8735 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8736 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8737 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8738 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8739 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8740 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8741 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8742 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8743 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8744 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8745 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8746 rsurface.modelgeneratedvertex = false;
8748 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8749 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8750 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8751 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8752 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8753 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8754 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8755 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8756 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8757 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8758 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8759 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8760 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8761 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8762 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8763 rsurface.modelelement3i = model->surfmesh.data_element3i;
8764 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8765 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8766 rsurface.modelelement3s = model->surfmesh.data_element3s;
8767 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8768 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8769 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8770 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8771 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8772 rsurface.modelsurfaces = model->data_surfaces;
8773 rsurface.batchgeneratedvertex = false;
8774 rsurface.batchfirstvertex = 0;
8775 rsurface.batchnumvertices = 0;
8776 rsurface.batchfirsttriangle = 0;
8777 rsurface.batchnumtriangles = 0;
8778 rsurface.batchvertex3f = NULL;
8779 rsurface.batchvertex3f_vertexbuffer = NULL;
8780 rsurface.batchvertex3f_bufferoffset = 0;
8781 rsurface.batchsvector3f = NULL;
8782 rsurface.batchsvector3f_vertexbuffer = NULL;
8783 rsurface.batchsvector3f_bufferoffset = 0;
8784 rsurface.batchtvector3f = NULL;
8785 rsurface.batchtvector3f_vertexbuffer = NULL;
8786 rsurface.batchtvector3f_bufferoffset = 0;
8787 rsurface.batchnormal3f = NULL;
8788 rsurface.batchnormal3f_vertexbuffer = NULL;
8789 rsurface.batchnormal3f_bufferoffset = 0;
8790 rsurface.batchlightmapcolor4f = NULL;
8791 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8792 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8793 rsurface.batchtexcoordtexture2f = NULL;
8794 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8795 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8796 rsurface.batchtexcoordlightmap2f = NULL;
8797 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8798 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8799 rsurface.batchskeletalindex4ub = NULL;
8800 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8801 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8802 rsurface.batchskeletalweight4ub = NULL;
8803 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8804 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8805 rsurface.batchvertexmesh = NULL;
8806 rsurface.batchvertexmesh_vertexbuffer = NULL;
8807 rsurface.batchvertexmesh_bufferoffset = 0;
8808 rsurface.batchelement3i = NULL;
8809 rsurface.batchelement3i_indexbuffer = NULL;
8810 rsurface.batchelement3i_bufferoffset = 0;
8811 rsurface.batchelement3s = NULL;
8812 rsurface.batchelement3s_indexbuffer = NULL;
8813 rsurface.batchelement3s_bufferoffset = 0;
8814 rsurface.passcolor4f = NULL;
8815 rsurface.passcolor4f_vertexbuffer = NULL;
8816 rsurface.passcolor4f_bufferoffset = 0;
8817 rsurface.forcecurrenttextureupdate = false;
8820 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)
8822 rsurface.entity = r_refdef.scene.worldentity;
8823 rsurface.skeleton = NULL;
8824 rsurface.ent_skinnum = 0;
8825 rsurface.ent_qwskin = -1;
8826 rsurface.ent_flags = entflags;
8827 rsurface.shadertime = r_refdef.scene.time - shadertime;
8828 rsurface.modelnumvertices = numvertices;
8829 rsurface.modelnumtriangles = numtriangles;
8830 rsurface.matrix = *matrix;
8831 rsurface.inversematrix = *inversematrix;
8832 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8833 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8834 R_EntityMatrix(&rsurface.matrix);
8835 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8836 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8837 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8838 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8839 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8840 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8841 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8842 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8843 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8844 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8845 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8846 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8847 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);
8848 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8849 rsurface.frameblend[0].lerp = 1;
8850 rsurface.ent_alttextures = false;
8851 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8852 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8853 rsurface.entityskeletaltransform3x4 = NULL;
8854 rsurface.entityskeletaltransform3x4buffer = NULL;
8855 rsurface.entityskeletaltransform3x4offset = 0;
8856 rsurface.entityskeletaltransform3x4size = 0;
8857 rsurface.entityskeletalnumtransforms = 0;
8858 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8859 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8860 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8861 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8864 rsurface.modelvertex3f = (float *)vertex3f;
8865 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8866 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8867 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8869 else if (wantnormals)
8871 rsurface.modelvertex3f = (float *)vertex3f;
8872 rsurface.modelsvector3f = NULL;
8873 rsurface.modeltvector3f = NULL;
8874 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8878 rsurface.modelvertex3f = (float *)vertex3f;
8879 rsurface.modelsvector3f = NULL;
8880 rsurface.modeltvector3f = NULL;
8881 rsurface.modelnormal3f = NULL;
8883 rsurface.modelvertexmesh = NULL;
8884 rsurface.modelvertexmesh_vertexbuffer = NULL;
8885 rsurface.modelvertexmesh_bufferoffset = 0;
8886 rsurface.modelvertex3f_vertexbuffer = 0;
8887 rsurface.modelvertex3f_bufferoffset = 0;
8888 rsurface.modelsvector3f_vertexbuffer = 0;
8889 rsurface.modelsvector3f_bufferoffset = 0;
8890 rsurface.modeltvector3f_vertexbuffer = 0;
8891 rsurface.modeltvector3f_bufferoffset = 0;
8892 rsurface.modelnormal3f_vertexbuffer = 0;
8893 rsurface.modelnormal3f_bufferoffset = 0;
8894 rsurface.modelgeneratedvertex = true;
8895 rsurface.modellightmapcolor4f = (float *)color4f;
8896 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8897 rsurface.modellightmapcolor4f_bufferoffset = 0;
8898 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8899 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8900 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8901 rsurface.modeltexcoordlightmap2f = NULL;
8902 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8903 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8904 rsurface.modelskeletalindex4ub = NULL;
8905 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8906 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8907 rsurface.modelskeletalweight4ub = NULL;
8908 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8909 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8910 rsurface.modelelement3i = (int *)element3i;
8911 rsurface.modelelement3i_indexbuffer = NULL;
8912 rsurface.modelelement3i_bufferoffset = 0;
8913 rsurface.modelelement3s = (unsigned short *)element3s;
8914 rsurface.modelelement3s_indexbuffer = NULL;
8915 rsurface.modelelement3s_bufferoffset = 0;
8916 rsurface.modellightmapoffsets = NULL;
8917 rsurface.modelsurfaces = NULL;
8918 rsurface.batchgeneratedvertex = false;
8919 rsurface.batchfirstvertex = 0;
8920 rsurface.batchnumvertices = 0;
8921 rsurface.batchfirsttriangle = 0;
8922 rsurface.batchnumtriangles = 0;
8923 rsurface.batchvertex3f = NULL;
8924 rsurface.batchvertex3f_vertexbuffer = NULL;
8925 rsurface.batchvertex3f_bufferoffset = 0;
8926 rsurface.batchsvector3f = NULL;
8927 rsurface.batchsvector3f_vertexbuffer = NULL;
8928 rsurface.batchsvector3f_bufferoffset = 0;
8929 rsurface.batchtvector3f = NULL;
8930 rsurface.batchtvector3f_vertexbuffer = NULL;
8931 rsurface.batchtvector3f_bufferoffset = 0;
8932 rsurface.batchnormal3f = NULL;
8933 rsurface.batchnormal3f_vertexbuffer = NULL;
8934 rsurface.batchnormal3f_bufferoffset = 0;
8935 rsurface.batchlightmapcolor4f = NULL;
8936 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8937 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8938 rsurface.batchtexcoordtexture2f = NULL;
8939 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8940 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8941 rsurface.batchtexcoordlightmap2f = NULL;
8942 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8943 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8944 rsurface.batchskeletalindex4ub = NULL;
8945 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8946 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8947 rsurface.batchskeletalweight4ub = NULL;
8948 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8949 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8950 rsurface.batchvertexmesh = NULL;
8951 rsurface.batchvertexmesh_vertexbuffer = NULL;
8952 rsurface.batchvertexmesh_bufferoffset = 0;
8953 rsurface.batchelement3i = NULL;
8954 rsurface.batchelement3i_indexbuffer = NULL;
8955 rsurface.batchelement3i_bufferoffset = 0;
8956 rsurface.batchelement3s = NULL;
8957 rsurface.batchelement3s_indexbuffer = NULL;
8958 rsurface.batchelement3s_bufferoffset = 0;
8959 rsurface.passcolor4f = NULL;
8960 rsurface.passcolor4f_vertexbuffer = NULL;
8961 rsurface.passcolor4f_bufferoffset = 0;
8962 rsurface.forcecurrenttextureupdate = true;
8964 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8966 if ((wantnormals || wanttangents) && !normal3f)
8968 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8969 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8971 if (wanttangents && !svector3f)
8973 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8974 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8975 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8980 float RSurf_FogPoint(const float *v)
8982 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8983 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8984 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8985 float FogHeightFade = r_refdef.fogheightfade;
8987 unsigned int fogmasktableindex;
8988 if (r_refdef.fogplaneviewabove)
8989 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8991 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8992 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8993 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8996 float RSurf_FogVertex(const float *v)
8998 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8999 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9000 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9001 float FogHeightFade = rsurface.fogheightfade;
9003 unsigned int fogmasktableindex;
9004 if (r_refdef.fogplaneviewabove)
9005 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9007 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9008 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9009 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9012 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9015 for (i = 0;i < numelements;i++)
9016 outelement3i[i] = inelement3i[i] + adjust;
9019 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9020 extern cvar_t gl_vbo;
9021 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9029 int surfacefirsttriangle;
9030 int surfacenumtriangles;
9031 int surfacefirstvertex;
9032 int surfaceendvertex;
9033 int surfacenumvertices;
9034 int batchnumsurfaces = texturenumsurfaces;
9035 int batchnumvertices;
9036 int batchnumtriangles;
9040 qboolean dynamicvertex;
9044 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9047 q3shaderinfo_deform_t *deform;
9048 const msurface_t *surface, *firstsurface;
9049 r_vertexmesh_t *vertexmesh;
9050 if (!texturenumsurfaces)
9052 // find vertex range of this surface batch
9054 firstsurface = texturesurfacelist[0];
9055 firsttriangle = firstsurface->num_firsttriangle;
9056 batchnumvertices = 0;
9057 batchnumtriangles = 0;
9058 firstvertex = endvertex = firstsurface->num_firstvertex;
9059 for (i = 0;i < texturenumsurfaces;i++)
9061 surface = texturesurfacelist[i];
9062 if (surface != firstsurface + i)
9064 surfacefirstvertex = surface->num_firstvertex;
9065 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9066 surfacenumvertices = surface->num_vertices;
9067 surfacenumtriangles = surface->num_triangles;
9068 if (firstvertex > surfacefirstvertex)
9069 firstvertex = surfacefirstvertex;
9070 if (endvertex < surfaceendvertex)
9071 endvertex = surfaceendvertex;
9072 batchnumvertices += surfacenumvertices;
9073 batchnumtriangles += surfacenumtriangles;
9076 r_refdef.stats[r_stat_batch_batches]++;
9078 r_refdef.stats[r_stat_batch_withgaps]++;
9079 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9080 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9081 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9083 // we now know the vertex range used, and if there are any gaps in it
9084 rsurface.batchfirstvertex = firstvertex;
9085 rsurface.batchnumvertices = endvertex - firstvertex;
9086 rsurface.batchfirsttriangle = firsttriangle;
9087 rsurface.batchnumtriangles = batchnumtriangles;
9089 // this variable holds flags for which properties have been updated that
9090 // may require regenerating vertexmesh array...
9093 // check if any dynamic vertex processing must occur
9094 dynamicvertex = false;
9096 // a cvar to force the dynamic vertex path to be taken, for debugging
9097 if (r_batch_debugdynamicvertexpath.integer)
9101 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9102 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9103 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9104 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9106 dynamicvertex = true;
9109 // if there is a chance of animated vertex colors, it's a dynamic batch
9110 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9114 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9115 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9116 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9117 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9119 dynamicvertex = true;
9120 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9123 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9125 switch (deform->deform)
9128 case Q3DEFORM_PROJECTIONSHADOW:
9129 case Q3DEFORM_TEXT0:
9130 case Q3DEFORM_TEXT1:
9131 case Q3DEFORM_TEXT2:
9132 case Q3DEFORM_TEXT3:
9133 case Q3DEFORM_TEXT4:
9134 case Q3DEFORM_TEXT5:
9135 case Q3DEFORM_TEXT6:
9136 case Q3DEFORM_TEXT7:
9139 case Q3DEFORM_AUTOSPRITE:
9142 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9143 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9144 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9145 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9147 dynamicvertex = true;
9148 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9149 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9151 case Q3DEFORM_AUTOSPRITE2:
9154 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9155 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9156 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9157 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9159 dynamicvertex = true;
9160 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9161 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9163 case Q3DEFORM_NORMAL:
9166 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9167 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9168 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9169 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9171 dynamicvertex = true;
9172 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9173 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9176 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9177 break; // if wavefunc is a nop, ignore this transform
9180 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9181 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9182 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9183 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9185 dynamicvertex = true;
9186 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9187 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9189 case Q3DEFORM_BULGE:
9192 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9193 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9194 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9195 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9197 dynamicvertex = true;
9198 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9199 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9202 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9203 break; // if wavefunc is a nop, ignore this transform
9206 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9207 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9208 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9209 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9211 dynamicvertex = true;
9212 batchneed |= BATCHNEED_ARRAY_VERTEX;
9213 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9217 switch(rsurface.texture->tcgen.tcgen)
9220 case Q3TCGEN_TEXTURE:
9222 case Q3TCGEN_LIGHTMAP:
9225 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9226 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9227 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9228 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9230 dynamicvertex = true;
9231 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9232 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9234 case Q3TCGEN_VECTOR:
9237 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9238 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9239 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9240 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9242 dynamicvertex = true;
9243 batchneed |= BATCHNEED_ARRAY_VERTEX;
9244 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9246 case Q3TCGEN_ENVIRONMENT:
9249 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9250 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9251 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9252 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9254 dynamicvertex = true;
9255 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9256 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9259 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9263 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9264 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9265 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9266 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9268 dynamicvertex = true;
9269 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9270 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9273 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9277 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9278 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9279 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9280 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9282 dynamicvertex = true;
9283 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9286 // when the model data has no vertex buffer (dynamic mesh), we need to
9288 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9289 batchneed |= BATCHNEED_NOGAPS;
9291 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9292 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9293 // we ensure this by treating the vertex batch as dynamic...
9294 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9298 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9299 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9300 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9301 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9303 dynamicvertex = true;
9308 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9309 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9310 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9311 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9312 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9313 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9314 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9315 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9318 // if needsupdate, we have to do a dynamic vertex batch for sure
9319 if (needsupdate & batchneed)
9323 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9324 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9325 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9326 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9328 dynamicvertex = true;
9331 // see if we need to build vertexmesh from arrays
9332 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9336 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9337 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9338 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9339 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9341 dynamicvertex = true;
9344 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9345 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9346 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9348 rsurface.batchvertex3f = rsurface.modelvertex3f;
9349 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9350 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9351 rsurface.batchsvector3f = rsurface.modelsvector3f;
9352 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9353 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9354 rsurface.batchtvector3f = rsurface.modeltvector3f;
9355 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9356 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9357 rsurface.batchnormal3f = rsurface.modelnormal3f;
9358 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9359 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9360 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9361 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9362 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9363 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9364 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9365 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9366 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9367 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9368 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9369 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9370 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9371 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9372 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9373 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9374 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9375 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9376 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9377 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9378 rsurface.batchelement3i = rsurface.modelelement3i;
9379 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9380 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9381 rsurface.batchelement3s = rsurface.modelelement3s;
9382 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9383 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9384 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9385 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9386 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9387 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9388 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9390 // if any dynamic vertex processing has to occur in software, we copy the
9391 // entire surface list together before processing to rebase the vertices
9392 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9394 // if any gaps exist and we do not have a static vertex buffer, we have to
9395 // copy the surface list together to avoid wasting upload bandwidth on the
9396 // vertices in the gaps.
9398 // if gaps exist and we have a static vertex buffer, we can choose whether
9399 // to combine the index buffer ranges into one dynamic index buffer or
9400 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9402 // in many cases the batch is reduced to one draw call.
9404 rsurface.batchmultidraw = false;
9405 rsurface.batchmultidrawnumsurfaces = 0;
9406 rsurface.batchmultidrawsurfacelist = NULL;
9410 // static vertex data, just set pointers...
9411 rsurface.batchgeneratedvertex = false;
9412 // if there are gaps, we want to build a combined index buffer,
9413 // otherwise use the original static buffer with an appropriate offset
9416 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9417 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9418 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9419 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9420 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9422 rsurface.batchmultidraw = true;
9423 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9424 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9427 // build a new triangle elements array for this batch
9428 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9429 rsurface.batchfirsttriangle = 0;
9431 for (i = 0;i < texturenumsurfaces;i++)
9433 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9434 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9435 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9436 numtriangles += surfacenumtriangles;
9438 rsurface.batchelement3i_indexbuffer = NULL;
9439 rsurface.batchelement3i_bufferoffset = 0;
9440 rsurface.batchelement3s = NULL;
9441 rsurface.batchelement3s_indexbuffer = NULL;
9442 rsurface.batchelement3s_bufferoffset = 0;
9443 if (endvertex <= 65536)
9445 // make a 16bit (unsigned short) index array if possible
9446 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9447 for (i = 0;i < numtriangles*3;i++)
9448 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9450 // upload buffer data for the copytriangles batch
9451 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9453 if (rsurface.batchelement3s)
9454 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9455 else if (rsurface.batchelement3i)
9456 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9461 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9462 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9463 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9464 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9469 // something needs software processing, do it for real...
9470 // we only directly handle separate array data in this case and then
9471 // generate interleaved data if needed...
9472 rsurface.batchgeneratedvertex = true;
9473 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9474 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9475 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9476 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9478 // now copy the vertex data into a combined array and make an index array
9479 // (this is what Quake3 does all the time)
9480 // we also apply any skeletal animation here that would have been done in
9481 // the vertex shader, because most of the dynamic vertex animation cases
9482 // need actual vertex positions and normals
9483 //if (dynamicvertex)
9485 rsurface.batchvertexmesh = NULL;
9486 rsurface.batchvertexmesh_vertexbuffer = NULL;
9487 rsurface.batchvertexmesh_bufferoffset = 0;
9488 rsurface.batchvertex3f = NULL;
9489 rsurface.batchvertex3f_vertexbuffer = NULL;
9490 rsurface.batchvertex3f_bufferoffset = 0;
9491 rsurface.batchsvector3f = NULL;
9492 rsurface.batchsvector3f_vertexbuffer = NULL;
9493 rsurface.batchsvector3f_bufferoffset = 0;
9494 rsurface.batchtvector3f = NULL;
9495 rsurface.batchtvector3f_vertexbuffer = NULL;
9496 rsurface.batchtvector3f_bufferoffset = 0;
9497 rsurface.batchnormal3f = NULL;
9498 rsurface.batchnormal3f_vertexbuffer = NULL;
9499 rsurface.batchnormal3f_bufferoffset = 0;
9500 rsurface.batchlightmapcolor4f = NULL;
9501 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9502 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9503 rsurface.batchtexcoordtexture2f = NULL;
9504 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9505 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9506 rsurface.batchtexcoordlightmap2f = NULL;
9507 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9508 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9509 rsurface.batchskeletalindex4ub = NULL;
9510 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9511 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9512 rsurface.batchskeletalweight4ub = NULL;
9513 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9514 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9515 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9516 rsurface.batchelement3i_indexbuffer = NULL;
9517 rsurface.batchelement3i_bufferoffset = 0;
9518 rsurface.batchelement3s = NULL;
9519 rsurface.batchelement3s_indexbuffer = NULL;
9520 rsurface.batchelement3s_bufferoffset = 0;
9521 rsurface.batchskeletaltransform3x4buffer = NULL;
9522 rsurface.batchskeletaltransform3x4offset = 0;
9523 rsurface.batchskeletaltransform3x4size = 0;
9524 // we'll only be setting up certain arrays as needed
9525 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9526 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9527 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9528 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9529 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9530 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9531 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9533 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9534 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9536 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9537 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9538 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9539 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9540 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9541 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9542 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9544 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9545 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9549 for (i = 0;i < texturenumsurfaces;i++)
9551 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9552 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9553 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9554 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9555 // copy only the data requested
9556 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9557 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9558 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9560 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9562 if (rsurface.batchvertex3f)
9563 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9565 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9567 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9569 if (rsurface.modelnormal3f)
9570 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9572 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9574 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9576 if (rsurface.modelsvector3f)
9578 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9579 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9583 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9584 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9587 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9589 if (rsurface.modellightmapcolor4f)
9590 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9592 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9594 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9596 if (rsurface.modeltexcoordtexture2f)
9597 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9599 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9601 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9603 if (rsurface.modeltexcoordlightmap2f)
9604 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9606 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9608 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9610 if (rsurface.modelskeletalindex4ub)
9612 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9613 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9617 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9618 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9619 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9620 for (j = 0;j < surfacenumvertices;j++)
9625 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9626 numvertices += surfacenumvertices;
9627 numtriangles += surfacenumtriangles;
9630 // generate a 16bit index array as well if possible
9631 // (in general, dynamic batches fit)
9632 if (numvertices <= 65536)
9634 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9635 for (i = 0;i < numtriangles*3;i++)
9636 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9639 // since we've copied everything, the batch now starts at 0
9640 rsurface.batchfirstvertex = 0;
9641 rsurface.batchnumvertices = batchnumvertices;
9642 rsurface.batchfirsttriangle = 0;
9643 rsurface.batchnumtriangles = batchnumtriangles;
9646 // apply skeletal animation that would have been done in the vertex shader
9647 if (rsurface.batchskeletaltransform3x4)
9649 const unsigned char *si;
9650 const unsigned char *sw;
9652 const float *b = rsurface.batchskeletaltransform3x4;
9653 float *vp, *vs, *vt, *vn;
9655 float m[3][4], n[3][4];
9656 float tp[3], ts[3], tt[3], tn[3];
9657 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9658 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9659 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9660 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9661 si = rsurface.batchskeletalindex4ub;
9662 sw = rsurface.batchskeletalweight4ub;
9663 vp = rsurface.batchvertex3f;
9664 vs = rsurface.batchsvector3f;
9665 vt = rsurface.batchtvector3f;
9666 vn = rsurface.batchnormal3f;
9667 memset(m[0], 0, sizeof(m));
9668 memset(n[0], 0, sizeof(n));
9669 for (i = 0;i < batchnumvertices;i++)
9671 t[0] = b + si[0]*12;
9674 // common case - only one matrix
9688 else if (sw[2] + sw[3])
9691 t[1] = b + si[1]*12;
9692 t[2] = b + si[2]*12;
9693 t[3] = b + si[3]*12;
9694 w[0] = sw[0] * (1.0f / 255.0f);
9695 w[1] = sw[1] * (1.0f / 255.0f);
9696 w[2] = sw[2] * (1.0f / 255.0f);
9697 w[3] = sw[3] * (1.0f / 255.0f);
9698 // blend the matrices
9699 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9700 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9701 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9702 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9703 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9704 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9705 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9706 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9707 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9708 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9709 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9710 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9715 t[1] = b + si[1]*12;
9716 w[0] = sw[0] * (1.0f / 255.0f);
9717 w[1] = sw[1] * (1.0f / 255.0f);
9718 // blend the matrices
9719 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9720 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9721 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9722 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9723 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9724 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9725 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9726 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9727 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9728 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9729 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9730 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9734 // modify the vertex
9736 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9737 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9738 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9742 // the normal transformation matrix is a set of cross products...
9743 CrossProduct(m[1], m[2], n[0]);
9744 CrossProduct(m[2], m[0], n[1]);
9745 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9747 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9748 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9749 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9750 VectorNormalize(vn);
9755 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9756 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9757 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9758 VectorNormalize(vs);
9761 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9762 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9763 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9764 VectorNormalize(vt);
9769 rsurface.batchskeletaltransform3x4 = NULL;
9770 rsurface.batchskeletalnumtransforms = 0;
9773 // q1bsp surfaces rendered in vertex color mode have to have colors
9774 // calculated based on lightstyles
9775 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9777 // generate color arrays for the surfaces in this list
9782 const unsigned char *lm;
9783 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9784 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9785 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9787 for (i = 0;i < texturenumsurfaces;i++)
9789 surface = texturesurfacelist[i];
9790 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9791 surfacenumvertices = surface->num_vertices;
9792 if (surface->lightmapinfo->samples)
9794 for (j = 0;j < surfacenumvertices;j++)
9796 lm = surface->lightmapinfo->samples + offsets[j];
9797 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9798 VectorScale(lm, scale, c);
9799 if (surface->lightmapinfo->styles[1] != 255)
9801 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9803 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9804 VectorMA(c, scale, lm, c);
9805 if (surface->lightmapinfo->styles[2] != 255)
9808 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9809 VectorMA(c, scale, lm, c);
9810 if (surface->lightmapinfo->styles[3] != 255)
9813 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9814 VectorMA(c, scale, lm, c);
9821 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);
9827 for (j = 0;j < surfacenumvertices;j++)
9829 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9836 // if vertices are deformed (sprite flares and things in maps, possibly
9837 // water waves, bulges and other deformations), modify the copied vertices
9839 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9841 switch (deform->deform)
9844 case Q3DEFORM_PROJECTIONSHADOW:
9845 case Q3DEFORM_TEXT0:
9846 case Q3DEFORM_TEXT1:
9847 case Q3DEFORM_TEXT2:
9848 case Q3DEFORM_TEXT3:
9849 case Q3DEFORM_TEXT4:
9850 case Q3DEFORM_TEXT5:
9851 case Q3DEFORM_TEXT6:
9852 case Q3DEFORM_TEXT7:
9855 case Q3DEFORM_AUTOSPRITE:
9856 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9857 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9858 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9859 VectorNormalize(newforward);
9860 VectorNormalize(newright);
9861 VectorNormalize(newup);
9862 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9863 // rsurface.batchvertex3f_vertexbuffer = NULL;
9864 // rsurface.batchvertex3f_bufferoffset = 0;
9865 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9866 // rsurface.batchsvector3f_vertexbuffer = NULL;
9867 // rsurface.batchsvector3f_bufferoffset = 0;
9868 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9869 // rsurface.batchtvector3f_vertexbuffer = NULL;
9870 // rsurface.batchtvector3f_bufferoffset = 0;
9871 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9872 // rsurface.batchnormal3f_vertexbuffer = NULL;
9873 // rsurface.batchnormal3f_bufferoffset = 0;
9874 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9875 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9876 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9877 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
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);
9879 // a single autosprite surface can contain multiple sprites...
9880 for (j = 0;j < batchnumvertices - 3;j += 4)
9882 VectorClear(center);
9883 for (i = 0;i < 4;i++)
9884 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9885 VectorScale(center, 0.25f, center);
9886 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9887 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9888 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9889 for (i = 0;i < 4;i++)
9891 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9892 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9895 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9896 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9897 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);
9899 case Q3DEFORM_AUTOSPRITE2:
9900 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9901 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9902 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9903 VectorNormalize(newforward);
9904 VectorNormalize(newright);
9905 VectorNormalize(newup);
9906 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9907 // rsurface.batchvertex3f_vertexbuffer = NULL;
9908 // rsurface.batchvertex3f_bufferoffset = 0;
9910 const float *v1, *v2;
9920 memset(shortest, 0, sizeof(shortest));
9921 // a single autosprite surface can contain multiple sprites...
9922 for (j = 0;j < batchnumvertices - 3;j += 4)
9924 VectorClear(center);
9925 for (i = 0;i < 4;i++)
9926 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9927 VectorScale(center, 0.25f, center);
9928 // find the two shortest edges, then use them to define the
9929 // axis vectors for rotating around the central axis
9930 for (i = 0;i < 6;i++)
9932 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9933 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9934 l = VectorDistance2(v1, v2);
9935 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9937 l += (1.0f / 1024.0f);
9938 if (shortest[0].length2 > l || i == 0)
9940 shortest[1] = shortest[0];
9941 shortest[0].length2 = l;
9942 shortest[0].v1 = v1;
9943 shortest[0].v2 = v2;
9945 else if (shortest[1].length2 > l || i == 1)
9947 shortest[1].length2 = l;
9948 shortest[1].v1 = v1;
9949 shortest[1].v2 = v2;
9952 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9953 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9954 // this calculates the right vector from the shortest edge
9955 // and the up vector from the edge midpoints
9956 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9957 VectorNormalize(right);
9958 VectorSubtract(end, start, up);
9959 VectorNormalize(up);
9960 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9961 VectorSubtract(rsurface.localvieworigin, center, forward);
9962 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9963 VectorNegate(forward, forward);
9964 VectorReflect(forward, 0, up, forward);
9965 VectorNormalize(forward);
9966 CrossProduct(up, forward, newright);
9967 VectorNormalize(newright);
9968 // rotate the quad around the up axis vector, this is made
9969 // especially easy by the fact we know the quad is flat,
9970 // so we only have to subtract the center position and
9971 // measure distance along the right vector, and then
9972 // multiply that by the newright vector and add back the
9974 // we also need to subtract the old position to undo the
9975 // displacement from the center, which we do with a
9976 // DotProduct, the subtraction/addition of center is also
9977 // optimized into DotProducts here
9978 l = DotProduct(right, center);
9979 for (i = 0;i < 4;i++)
9981 v1 = rsurface.batchvertex3f + 3*(j+i);
9982 f = DotProduct(right, v1) - l;
9983 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9987 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9989 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9990 // rsurface.batchnormal3f_vertexbuffer = NULL;
9991 // rsurface.batchnormal3f_bufferoffset = 0;
9992 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9994 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9996 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9997 // rsurface.batchsvector3f_vertexbuffer = NULL;
9998 // rsurface.batchsvector3f_bufferoffset = 0;
9999 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10000 // rsurface.batchtvector3f_vertexbuffer = NULL;
10001 // rsurface.batchtvector3f_bufferoffset = 0;
10002 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);
10005 case Q3DEFORM_NORMAL:
10006 // deform the normals to make reflections wavey
10007 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10008 rsurface.batchnormal3f_vertexbuffer = NULL;
10009 rsurface.batchnormal3f_bufferoffset = 0;
10010 for (j = 0;j < batchnumvertices;j++)
10013 float *normal = rsurface.batchnormal3f + 3*j;
10014 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10015 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10016 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10017 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10018 VectorNormalize(normal);
10020 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10022 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10023 // rsurface.batchsvector3f_vertexbuffer = NULL;
10024 // rsurface.batchsvector3f_bufferoffset = 0;
10025 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10026 // rsurface.batchtvector3f_vertexbuffer = NULL;
10027 // rsurface.batchtvector3f_bufferoffset = 0;
10028 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);
10031 case Q3DEFORM_WAVE:
10032 // deform vertex array to make wavey water and flags and such
10033 waveparms[0] = deform->waveparms[0];
10034 waveparms[1] = deform->waveparms[1];
10035 waveparms[2] = deform->waveparms[2];
10036 waveparms[3] = deform->waveparms[3];
10037 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10038 break; // if wavefunc is a nop, don't make a dynamic vertex array
10039 // this is how a divisor of vertex influence on deformation
10040 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10041 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10042 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10043 // rsurface.batchvertex3f_vertexbuffer = NULL;
10044 // rsurface.batchvertex3f_bufferoffset = 0;
10045 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10046 // rsurface.batchnormal3f_vertexbuffer = NULL;
10047 // rsurface.batchnormal3f_bufferoffset = 0;
10048 for (j = 0;j < batchnumvertices;j++)
10050 // if the wavefunc depends on time, evaluate it per-vertex
10053 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10054 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10056 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10058 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10059 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10060 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10062 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10063 // rsurface.batchsvector3f_vertexbuffer = NULL;
10064 // rsurface.batchsvector3f_bufferoffset = 0;
10065 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10066 // rsurface.batchtvector3f_vertexbuffer = NULL;
10067 // rsurface.batchtvector3f_bufferoffset = 0;
10068 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);
10071 case Q3DEFORM_BULGE:
10072 // deform vertex array to make the surface have moving bulges
10073 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10074 // rsurface.batchvertex3f_vertexbuffer = NULL;
10075 // rsurface.batchvertex3f_bufferoffset = 0;
10076 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10077 // rsurface.batchnormal3f_vertexbuffer = NULL;
10078 // rsurface.batchnormal3f_bufferoffset = 0;
10079 for (j = 0;j < batchnumvertices;j++)
10081 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10082 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10084 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10085 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10086 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10088 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10089 // rsurface.batchsvector3f_vertexbuffer = NULL;
10090 // rsurface.batchsvector3f_bufferoffset = 0;
10091 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10092 // rsurface.batchtvector3f_vertexbuffer = NULL;
10093 // rsurface.batchtvector3f_bufferoffset = 0;
10094 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);
10097 case Q3DEFORM_MOVE:
10098 // deform vertex array
10099 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10100 break; // if wavefunc is a nop, don't make a dynamic vertex array
10101 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10102 VectorScale(deform->parms, scale, waveparms);
10103 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10104 // rsurface.batchvertex3f_vertexbuffer = NULL;
10105 // rsurface.batchvertex3f_bufferoffset = 0;
10106 for (j = 0;j < batchnumvertices;j++)
10107 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10112 if (rsurface.batchtexcoordtexture2f)
10114 // generate texcoords based on the chosen texcoord source
10115 switch(rsurface.texture->tcgen.tcgen)
10118 case Q3TCGEN_TEXTURE:
10120 case Q3TCGEN_LIGHTMAP:
10121 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10122 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10123 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10124 if (rsurface.batchtexcoordlightmap2f)
10125 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10127 case Q3TCGEN_VECTOR:
10128 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10129 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10130 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10131 for (j = 0;j < batchnumvertices;j++)
10133 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10134 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10137 case Q3TCGEN_ENVIRONMENT:
10138 // make environment reflections using a spheremap
10139 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10140 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10141 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10142 for (j = 0;j < batchnumvertices;j++)
10144 // identical to Q3A's method, but executed in worldspace so
10145 // carried models can be shiny too
10147 float viewer[3], d, reflected[3], worldreflected[3];
10149 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10150 // VectorNormalize(viewer);
10152 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10154 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10155 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10156 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10157 // note: this is proportinal to viewer, so we can normalize later
10159 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10160 VectorNormalize(worldreflected);
10162 // note: this sphere map only uses world x and z!
10163 // so positive and negative y will LOOK THE SAME.
10164 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10165 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10169 // the only tcmod that needs software vertex processing is turbulent, so
10170 // check for it here and apply the changes if needed
10171 // and we only support that as the first one
10172 // (handling a mixture of turbulent and other tcmods would be problematic
10173 // without punting it entirely to a software path)
10174 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10176 amplitude = rsurface.texture->tcmods[0].parms[1];
10177 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10178 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10179 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10180 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10181 for (j = 0;j < batchnumvertices;j++)
10183 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);
10184 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10189 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10191 // convert the modified arrays to vertex structs
10192 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10193 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10194 // rsurface.batchvertexmesh_bufferoffset = 0;
10195 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10196 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10197 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10198 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10199 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10200 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10201 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10203 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10205 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10206 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10209 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10210 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10211 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10212 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10213 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10214 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10215 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10216 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10217 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10218 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10220 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10222 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10223 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10228 // upload buffer data for the dynamic batch
10229 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10231 if (rsurface.batchvertexmesh)
10232 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10235 if (rsurface.batchvertex3f)
10236 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10237 if (rsurface.batchsvector3f)
10238 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10239 if (rsurface.batchtvector3f)
10240 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10241 if (rsurface.batchnormal3f)
10242 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10243 if (rsurface.batchlightmapcolor4f)
10244 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10245 if (rsurface.batchtexcoordtexture2f)
10246 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10247 if (rsurface.batchtexcoordlightmap2f)
10248 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10249 if (rsurface.batchskeletalindex4ub)
10250 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10251 if (rsurface.batchskeletalweight4ub)
10252 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10254 if (rsurface.batchelement3s)
10255 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10256 else if (rsurface.batchelement3i)
10257 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10261 void RSurf_DrawBatch(void)
10263 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10264 // through the pipeline, killing it earlier in the pipeline would have
10265 // per-surface overhead rather than per-batch overhead, so it's best to
10266 // reject it here, before it hits glDraw.
10267 if (rsurface.batchnumtriangles == 0)
10270 // batch debugging code
10271 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10277 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10278 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10281 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10283 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10285 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10286 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);
10293 if (rsurface.batchmultidraw)
10295 // issue multiple draws rather than copying index data
10296 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10297 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10298 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10299 for (i = 0;i < numsurfaces;)
10301 // combine consecutive surfaces as one draw
10302 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10303 if (surfacelist[j] != surfacelist[k] + 1)
10305 firstvertex = surfacelist[i]->num_firstvertex;
10306 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10307 firsttriangle = surfacelist[i]->num_firsttriangle;
10308 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10309 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);
10315 // there is only one consecutive run of index data (may have been combined)
10316 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);
10320 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10322 // pick the closest matching water plane
10323 int planeindex, vertexindex, bestplaneindex = -1;
10327 r_waterstate_waterplane_t *p;
10328 qboolean prepared = false;
10330 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10332 if(p->camera_entity != rsurface.texture->camera_entity)
10337 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10339 if(rsurface.batchnumvertices == 0)
10342 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10344 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10345 d += fabs(PlaneDiff(vert, &p->plane));
10347 if (bestd > d || bestplaneindex < 0)
10350 bestplaneindex = planeindex;
10353 return bestplaneindex;
10354 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10355 // this situation though, as it might be better to render single larger
10356 // batches with useless stuff (backface culled for example) than to
10357 // render multiple smaller batches
10360 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10363 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10364 rsurface.passcolor4f_vertexbuffer = 0;
10365 rsurface.passcolor4f_bufferoffset = 0;
10366 for (i = 0;i < rsurface.batchnumvertices;i++)
10367 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10370 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10377 if (rsurface.passcolor4f)
10379 // generate color arrays
10380 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10381 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10382 rsurface.passcolor4f_vertexbuffer = 0;
10383 rsurface.passcolor4f_bufferoffset = 0;
10384 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)
10386 f = RSurf_FogVertex(v);
10395 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10396 rsurface.passcolor4f_vertexbuffer = 0;
10397 rsurface.passcolor4f_bufferoffset = 0;
10398 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10400 f = RSurf_FogVertex(v);
10409 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10416 if (!rsurface.passcolor4f)
10418 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10419 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10420 rsurface.passcolor4f_vertexbuffer = 0;
10421 rsurface.passcolor4f_bufferoffset = 0;
10422 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)
10424 f = RSurf_FogVertex(v);
10425 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10426 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10427 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10432 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10437 if (!rsurface.passcolor4f)
10439 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10440 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10441 rsurface.passcolor4f_vertexbuffer = 0;
10442 rsurface.passcolor4f_bufferoffset = 0;
10443 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10452 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10457 if (!rsurface.passcolor4f)
10459 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10460 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10461 rsurface.passcolor4f_vertexbuffer = 0;
10462 rsurface.passcolor4f_bufferoffset = 0;
10463 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10465 c2[0] = c[0] + r_refdef.scene.ambient;
10466 c2[1] = c[1] + r_refdef.scene.ambient;
10467 c2[2] = c[2] + r_refdef.scene.ambient;
10472 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10475 rsurface.passcolor4f = NULL;
10476 rsurface.passcolor4f_vertexbuffer = 0;
10477 rsurface.passcolor4f_bufferoffset = 0;
10478 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10479 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10480 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10481 GL_Color(r, g, b, a);
10482 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10483 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10484 R_Mesh_TexMatrix(0, NULL);
10488 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10490 // TODO: optimize applyfog && applycolor case
10491 // just apply fog if necessary, and tint the fog color array if necessary
10492 rsurface.passcolor4f = NULL;
10493 rsurface.passcolor4f_vertexbuffer = 0;
10494 rsurface.passcolor4f_bufferoffset = 0;
10495 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10496 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10497 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10498 GL_Color(r, g, b, a);
10502 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10505 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10506 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10507 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10508 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10509 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10510 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10511 GL_Color(r, g, b, a);
10515 static void RSurf_DrawBatch_GL11_ClampColor(void)
10520 if (!rsurface.passcolor4f)
10522 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10524 c2[0] = bound(0.0f, c1[0], 1.0f);
10525 c2[1] = bound(0.0f, c1[1], 1.0f);
10526 c2[2] = bound(0.0f, c1[2], 1.0f);
10527 c2[3] = bound(0.0f, c1[3], 1.0f);
10531 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10541 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10542 rsurface.passcolor4f_vertexbuffer = 0;
10543 rsurface.passcolor4f_bufferoffset = 0;
10544 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)
10546 f = -DotProduct(r_refdef.view.forward, n);
10548 f = f * 0.85 + 0.15; // work around so stuff won't get black
10549 f *= r_refdef.lightmapintensity;
10550 Vector4Set(c, f, f, f, 1);
10554 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10556 RSurf_DrawBatch_GL11_ApplyFakeLight();
10557 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10558 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10559 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10560 GL_Color(r, g, b, a);
10564 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10572 vec3_t ambientcolor;
10573 vec3_t diffusecolor;
10577 VectorCopy(rsurface.modellight_lightdir, lightdir);
10578 f = 0.5f * r_refdef.lightmapintensity;
10579 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10580 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10581 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10582 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10583 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10584 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10586 if (VectorLength2(diffusecolor) > 0)
10588 // q3-style directional shading
10589 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10590 rsurface.passcolor4f_vertexbuffer = 0;
10591 rsurface.passcolor4f_bufferoffset = 0;
10592 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)
10594 if ((f = DotProduct(n, lightdir)) > 0)
10595 VectorMA(ambientcolor, f, diffusecolor, c);
10597 VectorCopy(ambientcolor, c);
10604 *applycolor = false;
10608 *r = ambientcolor[0];
10609 *g = ambientcolor[1];
10610 *b = ambientcolor[2];
10611 rsurface.passcolor4f = NULL;
10612 rsurface.passcolor4f_vertexbuffer = 0;
10613 rsurface.passcolor4f_bufferoffset = 0;
10617 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10619 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10620 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10621 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10622 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10623 GL_Color(r, g, b, a);
10627 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10635 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10636 rsurface.passcolor4f_vertexbuffer = 0;
10637 rsurface.passcolor4f_bufferoffset = 0;
10639 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10641 f = 1 - RSurf_FogVertex(v);
10649 void RSurf_SetupDepthAndCulling(void)
10651 // submodels are biased to avoid z-fighting with world surfaces that they
10652 // may be exactly overlapping (avoids z-fighting artifacts on certain
10653 // doors and things in Quake maps)
10654 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10655 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10656 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10657 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10660 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10662 // transparent sky would be ridiculous
10663 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10665 R_SetupShader_Generic_NoTexture(false, false);
10666 skyrenderlater = true;
10667 RSurf_SetupDepthAndCulling();
10668 GL_DepthMask(true);
10669 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10670 // skymasking on them, and Quake3 never did sky masking (unlike
10671 // software Quake and software Quake2), so disable the sky masking
10672 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10673 // and skymasking also looks very bad when noclipping outside the
10674 // level, so don't use it then either.
10675 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10677 R_Mesh_ResetTextureState();
10678 if (skyrendermasked)
10680 R_SetupShader_DepthOrShadow(false, false, false);
10681 // depth-only (masking)
10682 GL_ColorMask(0,0,0,0);
10683 // just to make sure that braindead drivers don't draw
10684 // anything despite that colormask...
10685 GL_BlendFunc(GL_ZERO, GL_ONE);
10686 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10687 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10691 R_SetupShader_Generic_NoTexture(false, false);
10693 GL_BlendFunc(GL_ONE, GL_ZERO);
10694 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10695 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10696 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10699 if (skyrendermasked)
10700 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10702 R_Mesh_ResetTextureState();
10703 GL_Color(1, 1, 1, 1);
10706 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10707 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10708 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10710 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10714 // render screenspace normalmap to texture
10715 GL_DepthMask(true);
10716 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10721 // bind lightmap texture
10723 // water/refraction/reflection/camera surfaces have to be handled specially
10724 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10726 int start, end, startplaneindex;
10727 for (start = 0;start < texturenumsurfaces;start = end)
10729 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10730 if(startplaneindex < 0)
10732 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10733 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10737 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10739 // now that we have a batch using the same planeindex, render it
10740 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10742 // render water or distortion background
10743 GL_DepthMask(true);
10744 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);
10746 // blend surface on top
10747 GL_DepthMask(false);
10748 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10751 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10753 // render surface with reflection texture as input
10754 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10755 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);
10762 // render surface batch normally
10763 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10764 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);
10768 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10770 // OpenGL 1.3 path - anything not completely ancient
10771 qboolean applycolor;
10774 const texturelayer_t *layer;
10775 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);
10776 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10778 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10781 int layertexrgbscale;
10782 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10784 if (layerindex == 0)
10785 GL_AlphaTest(true);
10788 GL_AlphaTest(false);
10789 GL_DepthFunc(GL_EQUAL);
10792 GL_DepthMask(layer->depthmask && writedepth);
10793 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10794 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10796 layertexrgbscale = 4;
10797 VectorScale(layer->color, 0.25f, layercolor);
10799 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10801 layertexrgbscale = 2;
10802 VectorScale(layer->color, 0.5f, layercolor);
10806 layertexrgbscale = 1;
10807 VectorScale(layer->color, 1.0f, layercolor);
10809 layercolor[3] = layer->color[3];
10810 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10811 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10812 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10813 switch (layer->type)
10815 case TEXTURELAYERTYPE_LITTEXTURE:
10816 // single-pass lightmapped texture with 2x rgbscale
10817 R_Mesh_TexBind(0, r_texture_white);
10818 R_Mesh_TexMatrix(0, NULL);
10819 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10820 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10821 R_Mesh_TexBind(1, layer->texture);
10822 R_Mesh_TexMatrix(1, &layer->texmatrix);
10823 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10824 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10825 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10826 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10827 else if (FAKELIGHT_ENABLED)
10828 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10829 else if (rsurface.uselightmaptexture)
10830 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10832 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10834 case TEXTURELAYERTYPE_TEXTURE:
10835 // singletexture unlit texture with transparency support
10836 R_Mesh_TexBind(0, layer->texture);
10837 R_Mesh_TexMatrix(0, &layer->texmatrix);
10838 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10839 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10840 R_Mesh_TexBind(1, 0);
10841 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10842 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10844 case TEXTURELAYERTYPE_FOG:
10845 // singletexture fogging
10846 if (layer->texture)
10848 R_Mesh_TexBind(0, layer->texture);
10849 R_Mesh_TexMatrix(0, &layer->texmatrix);
10850 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10851 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10855 R_Mesh_TexBind(0, 0);
10856 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10858 R_Mesh_TexBind(1, 0);
10859 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10860 // generate a color array for the fog pass
10861 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10862 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10866 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10869 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10871 GL_DepthFunc(GL_LEQUAL);
10872 GL_AlphaTest(false);
10876 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10878 // OpenGL 1.1 - crusty old voodoo path
10881 const texturelayer_t *layer;
10882 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);
10883 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10885 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10887 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10889 if (layerindex == 0)
10890 GL_AlphaTest(true);
10893 GL_AlphaTest(false);
10894 GL_DepthFunc(GL_EQUAL);
10897 GL_DepthMask(layer->depthmask && writedepth);
10898 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10899 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10900 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10901 switch (layer->type)
10903 case TEXTURELAYERTYPE_LITTEXTURE:
10904 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10906 // two-pass lit texture with 2x rgbscale
10907 // first the lightmap pass
10908 R_Mesh_TexBind(0, r_texture_white);
10909 R_Mesh_TexMatrix(0, NULL);
10910 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10911 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10912 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10913 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10914 else if (FAKELIGHT_ENABLED)
10915 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10916 else if (rsurface.uselightmaptexture)
10917 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10919 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10920 // then apply the texture to it
10921 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10922 R_Mesh_TexBind(0, layer->texture);
10923 R_Mesh_TexMatrix(0, &layer->texmatrix);
10924 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10925 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10926 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);
10930 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10931 R_Mesh_TexBind(0, layer->texture);
10932 R_Mesh_TexMatrix(0, &layer->texmatrix);
10933 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10934 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10935 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10936 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);
10937 else if (FAKELIGHT_ENABLED)
10938 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);
10940 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);
10943 case TEXTURELAYERTYPE_TEXTURE:
10944 // singletexture unlit texture with transparency support
10945 R_Mesh_TexBind(0, layer->texture);
10946 R_Mesh_TexMatrix(0, &layer->texmatrix);
10947 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10948 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10949 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);
10951 case TEXTURELAYERTYPE_FOG:
10952 // singletexture fogging
10953 if (layer->texture)
10955 R_Mesh_TexBind(0, layer->texture);
10956 R_Mesh_TexMatrix(0, &layer->texmatrix);
10957 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10958 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10962 R_Mesh_TexBind(0, 0);
10963 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10965 // generate a color array for the fog pass
10966 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10967 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10971 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10974 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10976 GL_DepthFunc(GL_LEQUAL);
10977 GL_AlphaTest(false);
10981 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10985 r_vertexgeneric_t *batchvertex;
10988 // R_Mesh_ResetTextureState();
10989 R_SetupShader_Generic_NoTexture(false, false);
10991 if(rsurface.texture && rsurface.texture->currentskinframe)
10993 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10994 c[3] *= rsurface.texture->currentalpha;
11004 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11006 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11007 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11008 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11011 // brighten it up (as texture value 127 means "unlit")
11012 c[0] *= 2 * r_refdef.view.colorscale;
11013 c[1] *= 2 * r_refdef.view.colorscale;
11014 c[2] *= 2 * r_refdef.view.colorscale;
11016 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11017 c[3] *= r_wateralpha.value;
11019 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11021 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11022 GL_DepthMask(false);
11024 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11026 GL_BlendFunc(GL_ONE, GL_ONE);
11027 GL_DepthMask(false);
11029 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11031 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11032 GL_DepthMask(false);
11034 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11036 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11037 GL_DepthMask(false);
11041 GL_BlendFunc(GL_ONE, GL_ZERO);
11042 GL_DepthMask(writedepth);
11045 if (r_showsurfaces.integer == 3)
11047 rsurface.passcolor4f = NULL;
11049 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11051 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11053 rsurface.passcolor4f = NULL;
11054 rsurface.passcolor4f_vertexbuffer = 0;
11055 rsurface.passcolor4f_bufferoffset = 0;
11057 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11059 qboolean applycolor = true;
11062 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11064 r_refdef.lightmapintensity = 1;
11065 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11066 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11068 else if (FAKELIGHT_ENABLED)
11070 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11072 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11073 RSurf_DrawBatch_GL11_ApplyFakeLight();
11074 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11078 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11080 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11081 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11082 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11085 if(!rsurface.passcolor4f)
11086 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11088 RSurf_DrawBatch_GL11_ApplyAmbient();
11089 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11090 if(r_refdef.fogenabled)
11091 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11092 RSurf_DrawBatch_GL11_ClampColor();
11094 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11095 R_SetupShader_Generic_NoTexture(false, false);
11098 else if (!r_refdef.view.showdebug)
11100 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11101 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11102 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11104 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11105 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11107 R_Mesh_PrepareVertices_Generic_Unlock();
11110 else if (r_showsurfaces.integer == 4)
11112 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11113 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11114 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11116 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11117 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11118 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11120 R_Mesh_PrepareVertices_Generic_Unlock();
11123 else if (r_showsurfaces.integer == 2)
11126 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11127 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11128 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11130 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11131 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11132 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11133 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11134 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11135 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11136 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11138 R_Mesh_PrepareVertices_Generic_Unlock();
11139 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11143 int texturesurfaceindex;
11145 const msurface_t *surface;
11146 float surfacecolor4f[4];
11147 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11148 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11150 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11152 surface = texturesurfacelist[texturesurfaceindex];
11153 k = (int)(((size_t)surface) / sizeof(msurface_t));
11154 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11155 for (j = 0;j < surface->num_vertices;j++)
11157 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11158 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11162 R_Mesh_PrepareVertices_Generic_Unlock();
11167 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11170 RSurf_SetupDepthAndCulling();
11171 if (r_showsurfaces.integer)
11173 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11176 switch (vid.renderpath)
11178 case RENDERPATH_GL20:
11179 case RENDERPATH_D3D9:
11180 case RENDERPATH_D3D10:
11181 case RENDERPATH_D3D11:
11182 case RENDERPATH_SOFT:
11183 case RENDERPATH_GLES2:
11184 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11186 case RENDERPATH_GL13:
11187 case RENDERPATH_GLES1:
11188 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11190 case RENDERPATH_GL11:
11191 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11197 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11200 RSurf_SetupDepthAndCulling();
11201 if (r_showsurfaces.integer)
11203 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11206 switch (vid.renderpath)
11208 case RENDERPATH_GL20:
11209 case RENDERPATH_D3D9:
11210 case RENDERPATH_D3D10:
11211 case RENDERPATH_D3D11:
11212 case RENDERPATH_SOFT:
11213 case RENDERPATH_GLES2:
11214 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11216 case RENDERPATH_GL13:
11217 case RENDERPATH_GLES1:
11218 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11220 case RENDERPATH_GL11:
11221 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11227 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11230 int texturenumsurfaces, endsurface;
11231 texture_t *texture;
11232 const msurface_t *surface;
11233 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11235 // if the model is static it doesn't matter what value we give for
11236 // wantnormals and wanttangents, so this logic uses only rules applicable
11237 // to a model, knowing that they are meaningless otherwise
11238 if (ent == r_refdef.scene.worldentity)
11239 RSurf_ActiveWorldEntity();
11240 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11241 RSurf_ActiveModelEntity(ent, false, false, false);
11244 switch (vid.renderpath)
11246 case RENDERPATH_GL20:
11247 case RENDERPATH_D3D9:
11248 case RENDERPATH_D3D10:
11249 case RENDERPATH_D3D11:
11250 case RENDERPATH_SOFT:
11251 case RENDERPATH_GLES2:
11252 RSurf_ActiveModelEntity(ent, true, true, false);
11254 case RENDERPATH_GL11:
11255 case RENDERPATH_GL13:
11256 case RENDERPATH_GLES1:
11257 RSurf_ActiveModelEntity(ent, true, false, false);
11262 if (r_transparentdepthmasking.integer)
11264 qboolean setup = false;
11265 for (i = 0;i < numsurfaces;i = j)
11268 surface = rsurface.modelsurfaces + surfacelist[i];
11269 texture = surface->texture;
11270 rsurface.texture = R_GetCurrentTexture(texture);
11271 rsurface.lightmaptexture = NULL;
11272 rsurface.deluxemaptexture = NULL;
11273 rsurface.uselightmaptexture = false;
11274 // scan ahead until we find a different texture
11275 endsurface = min(i + 1024, numsurfaces);
11276 texturenumsurfaces = 0;
11277 texturesurfacelist[texturenumsurfaces++] = surface;
11278 for (;j < endsurface;j++)
11280 surface = rsurface.modelsurfaces + surfacelist[j];
11281 if (texture != surface->texture)
11283 texturesurfacelist[texturenumsurfaces++] = surface;
11285 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11287 // render the range of surfaces as depth
11291 GL_ColorMask(0,0,0,0);
11293 GL_DepthTest(true);
11294 GL_BlendFunc(GL_ONE, GL_ZERO);
11295 GL_DepthMask(true);
11296 // R_Mesh_ResetTextureState();
11298 RSurf_SetupDepthAndCulling();
11299 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11300 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11301 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11305 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11308 for (i = 0;i < numsurfaces;i = j)
11311 surface = rsurface.modelsurfaces + surfacelist[i];
11312 texture = surface->texture;
11313 rsurface.texture = R_GetCurrentTexture(texture);
11314 // scan ahead until we find a different texture
11315 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11316 texturenumsurfaces = 0;
11317 texturesurfacelist[texturenumsurfaces++] = surface;
11318 if(FAKELIGHT_ENABLED)
11320 rsurface.lightmaptexture = NULL;
11321 rsurface.deluxemaptexture = NULL;
11322 rsurface.uselightmaptexture = false;
11323 for (;j < endsurface;j++)
11325 surface = rsurface.modelsurfaces + surfacelist[j];
11326 if (texture != surface->texture)
11328 texturesurfacelist[texturenumsurfaces++] = surface;
11333 rsurface.lightmaptexture = surface->lightmaptexture;
11334 rsurface.deluxemaptexture = surface->deluxemaptexture;
11335 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11336 for (;j < endsurface;j++)
11338 surface = rsurface.modelsurfaces + surfacelist[j];
11339 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11341 texturesurfacelist[texturenumsurfaces++] = surface;
11344 // render the range of surfaces
11345 if (ent == r_refdef.scene.worldentity)
11346 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11348 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11350 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11353 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11355 // transparent surfaces get pushed off into the transparent queue
11356 int surfacelistindex;
11357 const msurface_t *surface;
11358 vec3_t tempcenter, center;
11359 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11361 surface = texturesurfacelist[surfacelistindex];
11362 if (r_transparent_sortsurfacesbynearest.integer)
11364 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11365 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11366 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11370 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11371 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11372 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11374 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11375 if (rsurface.entity->transparent_offset) // transparent offset
11377 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11378 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11379 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11381 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);
11385 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11387 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11389 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11391 RSurf_SetupDepthAndCulling();
11392 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11393 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11394 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11398 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11402 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11405 if (!rsurface.texture->currentnumlayers)
11407 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11408 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11410 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11412 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11413 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11414 else if (!rsurface.texture->currentnumlayers)
11416 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11418 // in the deferred case, transparent surfaces were queued during prepass
11419 if (!r_shadow_usingdeferredprepass)
11420 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11424 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11425 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11430 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11433 texture_t *texture;
11434 R_FrameData_SetMark();
11435 // break the surface list down into batches by texture and use of lightmapping
11436 for (i = 0;i < numsurfaces;i = j)
11439 // texture is the base texture pointer, rsurface.texture is the
11440 // current frame/skin the texture is directing us to use (for example
11441 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11442 // use skin 1 instead)
11443 texture = surfacelist[i]->texture;
11444 rsurface.texture = R_GetCurrentTexture(texture);
11445 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11447 // if this texture is not the kind we want, skip ahead to the next one
11448 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11452 if(FAKELIGHT_ENABLED || depthonly || prepass)
11454 rsurface.lightmaptexture = NULL;
11455 rsurface.deluxemaptexture = NULL;
11456 rsurface.uselightmaptexture = false;
11457 // simply scan ahead until we find a different texture or lightmap state
11458 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11463 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11464 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11465 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11466 // simply scan ahead until we find a different texture or lightmap state
11467 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11470 // render the range of surfaces
11471 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11473 R_FrameData_ReturnToMark();
11476 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11480 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11483 if (!rsurface.texture->currentnumlayers)
11485 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11486 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11488 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11490 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11491 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11492 else if (!rsurface.texture->currentnumlayers)
11494 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11496 // in the deferred case, transparent surfaces were queued during prepass
11497 if (!r_shadow_usingdeferredprepass)
11498 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11502 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11503 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11508 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11511 texture_t *texture;
11512 R_FrameData_SetMark();
11513 // break the surface list down into batches by texture and use of lightmapping
11514 for (i = 0;i < numsurfaces;i = j)
11517 // texture is the base texture pointer, rsurface.texture is the
11518 // current frame/skin the texture is directing us to use (for example
11519 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11520 // use skin 1 instead)
11521 texture = surfacelist[i]->texture;
11522 rsurface.texture = R_GetCurrentTexture(texture);
11523 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11525 // if this texture is not the kind we want, skip ahead to the next one
11526 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11530 if(FAKELIGHT_ENABLED || depthonly || prepass)
11532 rsurface.lightmaptexture = NULL;
11533 rsurface.deluxemaptexture = NULL;
11534 rsurface.uselightmaptexture = false;
11535 // simply scan ahead until we find a different texture or lightmap state
11536 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11541 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11542 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11543 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11544 // simply scan ahead until we find a different texture or lightmap state
11545 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11548 // render the range of surfaces
11549 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11551 R_FrameData_ReturnToMark();
11554 float locboxvertex3f[6*4*3] =
11556 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11557 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11558 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11559 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11560 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11561 1,0,0, 0,0,0, 0,1,0, 1,1,0
11564 unsigned short locboxelements[6*2*3] =
11569 12,13,14, 12,14,15,
11570 16,17,18, 16,18,19,
11574 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11577 cl_locnode_t *loc = (cl_locnode_t *)ent;
11579 float vertex3f[6*4*3];
11581 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11582 GL_DepthMask(false);
11583 GL_DepthRange(0, 1);
11584 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11585 GL_DepthTest(true);
11586 GL_CullFace(GL_NONE);
11587 R_EntityMatrix(&identitymatrix);
11589 // R_Mesh_ResetTextureState();
11591 i = surfacelist[0];
11592 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11593 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11594 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11595 surfacelist[0] < 0 ? 0.5f : 0.125f);
11597 if (VectorCompare(loc->mins, loc->maxs))
11599 VectorSet(size, 2, 2, 2);
11600 VectorMA(loc->mins, -0.5f, size, mins);
11604 VectorCopy(loc->mins, mins);
11605 VectorSubtract(loc->maxs, loc->mins, size);
11608 for (i = 0;i < 6*4*3;)
11609 for (j = 0;j < 3;j++, i++)
11610 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11612 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11613 R_SetupShader_Generic_NoTexture(false, false);
11614 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11617 void R_DrawLocs(void)
11620 cl_locnode_t *loc, *nearestloc;
11622 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11623 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11625 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11626 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11630 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11632 if (decalsystem->decals)
11633 Mem_Free(decalsystem->decals);
11634 memset(decalsystem, 0, sizeof(*decalsystem));
11637 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, unsigned int decalsequence)
11640 tridecal_t *decals;
11643 // expand or initialize the system
11644 if (decalsystem->maxdecals <= decalsystem->numdecals)
11646 decalsystem_t old = *decalsystem;
11647 qboolean useshortelements;
11648 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11649 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11650 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)));
11651 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11652 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11653 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11654 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11655 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11656 if (decalsystem->numdecals)
11657 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11659 Mem_Free(old.decals);
11660 for (i = 0;i < decalsystem->maxdecals*3;i++)
11661 decalsystem->element3i[i] = i;
11662 if (useshortelements)
11663 for (i = 0;i < decalsystem->maxdecals*3;i++)
11664 decalsystem->element3s[i] = i;
11667 // grab a decal and search for another free slot for the next one
11668 decals = decalsystem->decals;
11669 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11670 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11672 decalsystem->freedecal = i;
11673 if (decalsystem->numdecals <= i)
11674 decalsystem->numdecals = i + 1;
11676 // initialize the decal
11678 decal->triangleindex = triangleindex;
11679 decal->surfaceindex = surfaceindex;
11680 decal->decalsequence = decalsequence;
11681 decal->color4f[0][0] = c0[0];
11682 decal->color4f[0][1] = c0[1];
11683 decal->color4f[0][2] = c0[2];
11684 decal->color4f[0][3] = 1;
11685 decal->color4f[1][0] = c1[0];
11686 decal->color4f[1][1] = c1[1];
11687 decal->color4f[1][2] = c1[2];
11688 decal->color4f[1][3] = 1;
11689 decal->color4f[2][0] = c2[0];
11690 decal->color4f[2][1] = c2[1];
11691 decal->color4f[2][2] = c2[2];
11692 decal->color4f[2][3] = 1;
11693 decal->vertex3f[0][0] = v0[0];
11694 decal->vertex3f[0][1] = v0[1];
11695 decal->vertex3f[0][2] = v0[2];
11696 decal->vertex3f[1][0] = v1[0];
11697 decal->vertex3f[1][1] = v1[1];
11698 decal->vertex3f[1][2] = v1[2];
11699 decal->vertex3f[2][0] = v2[0];
11700 decal->vertex3f[2][1] = v2[1];
11701 decal->vertex3f[2][2] = v2[2];
11702 decal->texcoord2f[0][0] = t0[0];
11703 decal->texcoord2f[0][1] = t0[1];
11704 decal->texcoord2f[1][0] = t1[0];
11705 decal->texcoord2f[1][1] = t1[1];
11706 decal->texcoord2f[2][0] = t2[0];
11707 decal->texcoord2f[2][1] = t2[1];
11708 TriangleNormal(v0, v1, v2, decal->plane);
11709 VectorNormalize(decal->plane);
11710 decal->plane[3] = DotProduct(v0, decal->plane);
11713 extern cvar_t cl_decals_bias;
11714 extern cvar_t cl_decals_models;
11715 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11716 // baseparms, parms, temps
11717 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, unsigned int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11722 const float *vertex3f;
11723 const float *normal3f;
11725 float points[2][9][3];
11732 e = rsurface.modelelement3i + 3*triangleindex;
11734 vertex3f = rsurface.modelvertex3f;
11735 normal3f = rsurface.modelnormal3f;
11739 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11741 index = 3*e[cornerindex];
11742 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11747 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11749 index = 3*e[cornerindex];
11750 VectorCopy(vertex3f + index, v[cornerindex]);
11755 //TriangleNormal(v[0], v[1], v[2], normal);
11756 //if (DotProduct(normal, localnormal) < 0.0f)
11758 // clip by each of the box planes formed from the projection matrix
11759 // if anything survives, we emit the decal
11760 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]);
11763 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]);
11766 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]);
11769 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]);
11772 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]);
11775 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]);
11778 // some part of the triangle survived, so we have to accept it...
11781 // dynamic always uses the original triangle
11783 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11785 index = 3*e[cornerindex];
11786 VectorCopy(vertex3f + index, v[cornerindex]);
11789 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11791 // convert vertex positions to texcoords
11792 Matrix4x4_Transform(projection, v[cornerindex], temp);
11793 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11794 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11795 // calculate distance fade from the projection origin
11796 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11797 f = bound(0.0f, f, 1.0f);
11798 c[cornerindex][0] = r * f;
11799 c[cornerindex][1] = g * f;
11800 c[cornerindex][2] = b * f;
11801 c[cornerindex][3] = 1.0f;
11802 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11805 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);
11807 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11808 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);
11810 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, unsigned int decalsequence)
11812 matrix4x4_t projection;
11813 decalsystem_t *decalsystem;
11816 const msurface_t *surface;
11817 const msurface_t *surfaces;
11818 const int *surfacelist;
11819 const texture_t *texture;
11821 int numsurfacelist;
11822 int surfacelistindex;
11825 float localorigin[3];
11826 float localnormal[3];
11827 float localmins[3];
11828 float localmaxs[3];
11831 float planes[6][4];
11834 int bih_triangles_count;
11835 int bih_triangles[256];
11836 int bih_surfaces[256];
11838 decalsystem = &ent->decalsystem;
11839 model = ent->model;
11840 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11842 R_DecalSystem_Reset(&ent->decalsystem);
11846 if (!model->brush.data_leafs && !cl_decals_models.integer)
11848 if (decalsystem->model)
11849 R_DecalSystem_Reset(decalsystem);
11853 if (decalsystem->model != model)
11854 R_DecalSystem_Reset(decalsystem);
11855 decalsystem->model = model;
11857 RSurf_ActiveModelEntity(ent, true, false, false);
11859 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11860 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11861 VectorNormalize(localnormal);
11862 localsize = worldsize*rsurface.inversematrixscale;
11863 localmins[0] = localorigin[0] - localsize;
11864 localmins[1] = localorigin[1] - localsize;
11865 localmins[2] = localorigin[2] - localsize;
11866 localmaxs[0] = localorigin[0] + localsize;
11867 localmaxs[1] = localorigin[1] + localsize;
11868 localmaxs[2] = localorigin[2] + localsize;
11870 //VectorCopy(localnormal, planes[4]);
11871 //VectorVectors(planes[4], planes[2], planes[0]);
11872 AnglesFromVectors(angles, localnormal, NULL, false);
11873 AngleVectors(angles, planes[0], planes[2], planes[4]);
11874 VectorNegate(planes[0], planes[1]);
11875 VectorNegate(planes[2], planes[3]);
11876 VectorNegate(planes[4], planes[5]);
11877 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11878 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11879 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11880 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11881 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11882 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11887 matrix4x4_t forwardprojection;
11888 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11889 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11894 float projectionvector[4][3];
11895 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11896 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11897 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11898 projectionvector[0][0] = planes[0][0] * ilocalsize;
11899 projectionvector[0][1] = planes[1][0] * ilocalsize;
11900 projectionvector[0][2] = planes[2][0] * ilocalsize;
11901 projectionvector[1][0] = planes[0][1] * ilocalsize;
11902 projectionvector[1][1] = planes[1][1] * ilocalsize;
11903 projectionvector[1][2] = planes[2][1] * ilocalsize;
11904 projectionvector[2][0] = planes[0][2] * ilocalsize;
11905 projectionvector[2][1] = planes[1][2] * ilocalsize;
11906 projectionvector[2][2] = planes[2][2] * ilocalsize;
11907 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11908 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11909 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11910 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11914 dynamic = model->surfmesh.isanimated;
11915 numsurfacelist = model->nummodelsurfaces;
11916 surfacelist = model->sortedmodelsurfaces;
11917 surfaces = model->data_surfaces;
11920 bih_triangles_count = -1;
11923 if(model->render_bih.numleafs)
11924 bih = &model->render_bih;
11925 else if(model->collision_bih.numleafs)
11926 bih = &model->collision_bih;
11929 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11930 if(bih_triangles_count == 0)
11932 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11934 if(bih_triangles_count > 0)
11936 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11938 surfaceindex = bih_surfaces[triangleindex];
11939 surface = surfaces + surfaceindex;
11940 texture = surface->texture;
11941 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11943 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11945 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11950 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11952 surfaceindex = surfacelist[surfacelistindex];
11953 surface = surfaces + surfaceindex;
11954 // check cull box first because it rejects more than any other check
11955 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11957 // skip transparent surfaces
11958 texture = surface->texture;
11959 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11961 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11963 numtriangles = surface->num_triangles;
11964 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11965 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11970 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11971 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, unsigned int decalsequence)
11973 int renderentityindex;
11974 float worldmins[3];
11975 float worldmaxs[3];
11976 entity_render_t *ent;
11978 if (!cl_decals_newsystem.integer)
11981 worldmins[0] = worldorigin[0] - worldsize;
11982 worldmins[1] = worldorigin[1] - worldsize;
11983 worldmins[2] = worldorigin[2] - worldsize;
11984 worldmaxs[0] = worldorigin[0] + worldsize;
11985 worldmaxs[1] = worldorigin[1] + worldsize;
11986 worldmaxs[2] = worldorigin[2] + worldsize;
11988 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11990 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11992 ent = r_refdef.scene.entities[renderentityindex];
11993 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11996 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12000 typedef struct r_decalsystem_splatqueue_s
12002 vec3_t worldorigin;
12003 vec3_t worldnormal;
12007 unsigned int decalsequence;
12009 r_decalsystem_splatqueue_t;
12011 int r_decalsystem_numqueued = 0;
12012 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12014 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)
12016 r_decalsystem_splatqueue_t *queue;
12018 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12021 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12022 VectorCopy(worldorigin, queue->worldorigin);
12023 VectorCopy(worldnormal, queue->worldnormal);
12024 Vector4Set(queue->color, r, g, b, a);
12025 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12026 queue->worldsize = worldsize;
12027 queue->decalsequence = cl.decalsequence++;
12030 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12033 r_decalsystem_splatqueue_t *queue;
12035 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12036 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);
12037 r_decalsystem_numqueued = 0;
12040 extern cvar_t cl_decals_max;
12041 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12044 decalsystem_t *decalsystem = &ent->decalsystem;
12046 unsigned int killsequence;
12051 if (!decalsystem->numdecals)
12054 if (r_showsurfaces.integer)
12057 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12059 R_DecalSystem_Reset(decalsystem);
12063 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12064 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12066 if (decalsystem->lastupdatetime)
12067 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12070 decalsystem->lastupdatetime = r_refdef.scene.time;
12071 numdecals = decalsystem->numdecals;
12073 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12075 if (decal->color4f[0][3])
12077 decal->lived += frametime;
12078 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12080 memset(decal, 0, sizeof(*decal));
12081 if (decalsystem->freedecal > i)
12082 decalsystem->freedecal = i;
12086 decal = decalsystem->decals;
12087 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12090 // collapse the array by shuffling the tail decals into the gaps
12093 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12094 decalsystem->freedecal++;
12095 if (decalsystem->freedecal == numdecals)
12097 decal[decalsystem->freedecal] = decal[--numdecals];
12100 decalsystem->numdecals = numdecals;
12102 if (numdecals <= 0)
12104 // if there are no decals left, reset decalsystem
12105 R_DecalSystem_Reset(decalsystem);
12109 extern skinframe_t *decalskinframe;
12110 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12113 decalsystem_t *decalsystem = &ent->decalsystem;
12122 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12125 numdecals = decalsystem->numdecals;
12129 if (r_showsurfaces.integer)
12132 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12134 R_DecalSystem_Reset(decalsystem);
12138 // if the model is static it doesn't matter what value we give for
12139 // wantnormals and wanttangents, so this logic uses only rules applicable
12140 // to a model, knowing that they are meaningless otherwise
12141 if (ent == r_refdef.scene.worldentity)
12142 RSurf_ActiveWorldEntity();
12144 RSurf_ActiveModelEntity(ent, false, false, false);
12146 decalsystem->lastupdatetime = r_refdef.scene.time;
12148 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12150 // update vertex positions for animated models
12151 v3f = decalsystem->vertex3f;
12152 c4f = decalsystem->color4f;
12153 t2f = decalsystem->texcoord2f;
12154 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12156 if (!decal->color4f[0][3])
12159 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12163 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12166 // update color values for fading decals
12167 if (decal->lived >= cl_decals_time.value)
12168 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12172 c4f[ 0] = decal->color4f[0][0] * alpha;
12173 c4f[ 1] = decal->color4f[0][1] * alpha;
12174 c4f[ 2] = decal->color4f[0][2] * alpha;
12176 c4f[ 4] = decal->color4f[1][0] * alpha;
12177 c4f[ 5] = decal->color4f[1][1] * alpha;
12178 c4f[ 6] = decal->color4f[1][2] * alpha;
12180 c4f[ 8] = decal->color4f[2][0] * alpha;
12181 c4f[ 9] = decal->color4f[2][1] * alpha;
12182 c4f[10] = decal->color4f[2][2] * alpha;
12185 t2f[0] = decal->texcoord2f[0][0];
12186 t2f[1] = decal->texcoord2f[0][1];
12187 t2f[2] = decal->texcoord2f[1][0];
12188 t2f[3] = decal->texcoord2f[1][1];
12189 t2f[4] = decal->texcoord2f[2][0];
12190 t2f[5] = decal->texcoord2f[2][1];
12192 // update vertex positions for animated models
12193 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12195 e = rsurface.modelelement3i + 3*decal->triangleindex;
12196 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12197 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12198 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12202 VectorCopy(decal->vertex3f[0], v3f);
12203 VectorCopy(decal->vertex3f[1], v3f + 3);
12204 VectorCopy(decal->vertex3f[2], v3f + 6);
12207 if (r_refdef.fogenabled)
12209 alpha = RSurf_FogVertex(v3f);
12210 VectorScale(c4f, alpha, c4f);
12211 alpha = RSurf_FogVertex(v3f + 3);
12212 VectorScale(c4f + 4, alpha, c4f + 4);
12213 alpha = RSurf_FogVertex(v3f + 6);
12214 VectorScale(c4f + 8, alpha, c4f + 8);
12225 r_refdef.stats[r_stat_drawndecals] += numtris;
12227 // now render the decals all at once
12228 // (this assumes they all use one particle font texture!)
12229 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);
12230 // R_Mesh_ResetTextureState();
12231 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12232 GL_DepthMask(false);
12233 GL_DepthRange(0, 1);
12234 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12235 GL_DepthTest(true);
12236 GL_CullFace(GL_NONE);
12237 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12238 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12239 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12243 static void R_DrawModelDecals(void)
12247 // fade faster when there are too many decals
12248 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12249 for (i = 0;i < r_refdef.scene.numentities;i++)
12250 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12252 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12253 for (i = 0;i < r_refdef.scene.numentities;i++)
12254 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12255 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12257 R_DecalSystem_ApplySplatEntitiesQueue();
12259 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12260 for (i = 0;i < r_refdef.scene.numentities;i++)
12261 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12263 r_refdef.stats[r_stat_totaldecals] += numdecals;
12265 if (r_showsurfaces.integer)
12268 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12270 for (i = 0;i < r_refdef.scene.numentities;i++)
12272 if (!r_refdef.viewcache.entityvisible[i])
12274 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12275 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12279 extern cvar_t mod_collision_bih;
12280 static void R_DrawDebugModel(void)
12282 entity_render_t *ent = rsurface.entity;
12283 int i, j, flagsmask;
12284 const msurface_t *surface;
12285 dp_model_t *model = ent->model;
12287 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12290 if (r_showoverdraw.value > 0)
12292 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12293 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12294 R_SetupShader_Generic_NoTexture(false, false);
12295 GL_DepthTest(false);
12296 GL_DepthMask(false);
12297 GL_DepthRange(0, 1);
12298 GL_BlendFunc(GL_ONE, GL_ONE);
12299 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12301 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12303 rsurface.texture = R_GetCurrentTexture(surface->texture);
12304 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12306 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12307 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12308 if (!rsurface.texture->currentlayers->depthmask)
12309 GL_Color(c, 0, 0, 1.0f);
12310 else if (ent == r_refdef.scene.worldentity)
12311 GL_Color(c, c, c, 1.0f);
12313 GL_Color(0, c, 0, 1.0f);
12314 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12318 rsurface.texture = NULL;
12321 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12323 // R_Mesh_ResetTextureState();
12324 R_SetupShader_Generic_NoTexture(false, false);
12325 GL_DepthRange(0, 1);
12326 GL_DepthTest(!r_showdisabledepthtest.integer);
12327 GL_DepthMask(false);
12328 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12330 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12334 qboolean cullbox = false;
12335 const q3mbrush_t *brush;
12336 const bih_t *bih = &model->collision_bih;
12337 const bih_leaf_t *bihleaf;
12338 float vertex3f[3][3];
12339 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12340 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12342 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12344 switch (bihleaf->type)
12347 brush = model->brush.data_brushes + bihleaf->itemindex;
12348 if (brush->colbrushf && brush->colbrushf->numtriangles)
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(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12352 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12355 case BIH_COLLISIONTRIANGLE:
12356 triangleindex = bihleaf->itemindex;
12357 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12358 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12359 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12360 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);
12361 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12362 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12364 case BIH_RENDERTRIANGLE:
12365 triangleindex = bihleaf->itemindex;
12366 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12367 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12368 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12369 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);
12370 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12371 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12377 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12380 if (r_showtris.integer && qglPolygonMode)
12382 if (r_showdisabledepthtest.integer)
12384 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12385 GL_DepthMask(false);
12389 GL_BlendFunc(GL_ONE, GL_ZERO);
12390 GL_DepthMask(true);
12392 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12393 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12395 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12397 rsurface.texture = R_GetCurrentTexture(surface->texture);
12398 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12400 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12401 if (!rsurface.texture->currentlayers->depthmask)
12402 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12403 else if (ent == r_refdef.scene.worldentity)
12404 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12406 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12407 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12411 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12412 rsurface.texture = NULL;
12415 if (r_shownormals.value != 0 && qglBegin)
12419 if (r_showdisabledepthtest.integer)
12421 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12422 GL_DepthMask(false);
12426 GL_BlendFunc(GL_ONE, GL_ZERO);
12427 GL_DepthMask(true);
12429 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12431 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12433 rsurface.texture = R_GetCurrentTexture(surface->texture);
12434 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12436 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12437 qglBegin(GL_LINES);
12438 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12440 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12442 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12443 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12444 qglVertex3f(v[0], v[1], v[2]);
12445 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12446 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12447 qglVertex3f(v[0], v[1], v[2]);
12450 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12452 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12454 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12455 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12456 qglVertex3f(v[0], v[1], v[2]);
12457 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12458 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12459 qglVertex3f(v[0], v[1], v[2]);
12462 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12464 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12466 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12467 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12468 qglVertex3f(v[0], v[1], v[2]);
12469 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12470 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12471 qglVertex3f(v[0], v[1], v[2]);
12474 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12476 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12478 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12479 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12480 qglVertex3f(v[0], v[1], v[2]);
12481 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12482 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12483 qglVertex3f(v[0], v[1], v[2]);
12490 rsurface.texture = NULL;
12495 int r_maxsurfacelist = 0;
12496 const msurface_t **r_surfacelist = NULL;
12497 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12499 int i, j, endj, flagsmask;
12500 dp_model_t *model = r_refdef.scene.worldmodel;
12501 msurface_t *surfaces;
12502 unsigned char *update;
12503 int numsurfacelist = 0;
12507 if (r_maxsurfacelist < model->num_surfaces)
12509 r_maxsurfacelist = model->num_surfaces;
12511 Mem_Free((msurface_t**)r_surfacelist);
12512 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12515 RSurf_ActiveWorldEntity();
12517 surfaces = model->data_surfaces;
12518 update = model->brushq1.lightmapupdateflags;
12520 // update light styles on this submodel
12521 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12523 model_brush_lightstyleinfo_t *style;
12524 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12526 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12528 int *list = style->surfacelist;
12529 style->value = r_refdef.scene.lightstylevalue[style->style];
12530 for (j = 0;j < style->numsurfaces;j++)
12531 update[list[j]] = true;
12536 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12540 R_DrawDebugModel();
12541 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12545 rsurface.lightmaptexture = NULL;
12546 rsurface.deluxemaptexture = NULL;
12547 rsurface.uselightmaptexture = false;
12548 rsurface.texture = NULL;
12549 rsurface.rtlight = NULL;
12550 numsurfacelist = 0;
12551 // add visible surfaces to draw list
12552 for (i = 0;i < model->nummodelsurfaces;i++)
12554 j = model->sortedmodelsurfaces[i];
12555 if (r_refdef.viewcache.world_surfacevisible[j])
12556 r_surfacelist[numsurfacelist++] = surfaces + j;
12558 // update lightmaps if needed
12559 if (model->brushq1.firstrender)
12561 model->brushq1.firstrender = false;
12562 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12564 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12568 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12569 if (r_refdef.viewcache.world_surfacevisible[j])
12571 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12573 // don't do anything if there were no surfaces
12574 if (!numsurfacelist)
12576 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12579 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12581 // add to stats if desired
12582 if (r_speeds.integer && !skysurfaces && !depthonly)
12584 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12585 for (j = 0;j < numsurfacelist;j++)
12586 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12589 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12592 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12594 int i, j, endj, flagsmask;
12595 dp_model_t *model = ent->model;
12596 msurface_t *surfaces;
12597 unsigned char *update;
12598 int numsurfacelist = 0;
12602 if (r_maxsurfacelist < model->num_surfaces)
12604 r_maxsurfacelist = model->num_surfaces;
12606 Mem_Free((msurface_t **)r_surfacelist);
12607 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12610 // if the model is static it doesn't matter what value we give for
12611 // wantnormals and wanttangents, so this logic uses only rules applicable
12612 // to a model, knowing that they are meaningless otherwise
12613 if (ent == r_refdef.scene.worldentity)
12614 RSurf_ActiveWorldEntity();
12615 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12616 RSurf_ActiveModelEntity(ent, false, false, false);
12618 RSurf_ActiveModelEntity(ent, true, true, true);
12619 else if (depthonly)
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, model->wantnormals, model->wanttangents, false);
12631 case RENDERPATH_GL11:
12632 case RENDERPATH_GL13:
12633 case RENDERPATH_GLES1:
12634 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12640 switch (vid.renderpath)
12642 case RENDERPATH_GL20:
12643 case RENDERPATH_D3D9:
12644 case RENDERPATH_D3D10:
12645 case RENDERPATH_D3D11:
12646 case RENDERPATH_SOFT:
12647 case RENDERPATH_GLES2:
12648 RSurf_ActiveModelEntity(ent, true, true, false);
12650 case RENDERPATH_GL11:
12651 case RENDERPATH_GL13:
12652 case RENDERPATH_GLES1:
12653 RSurf_ActiveModelEntity(ent, true, false, false);
12658 surfaces = model->data_surfaces;
12659 update = model->brushq1.lightmapupdateflags;
12661 // update light styles
12662 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12664 model_brush_lightstyleinfo_t *style;
12665 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12667 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12669 int *list = style->surfacelist;
12670 style->value = r_refdef.scene.lightstylevalue[style->style];
12671 for (j = 0;j < style->numsurfaces;j++)
12672 update[list[j]] = true;
12677 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12681 R_DrawDebugModel();
12682 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12686 rsurface.lightmaptexture = NULL;
12687 rsurface.deluxemaptexture = NULL;
12688 rsurface.uselightmaptexture = false;
12689 rsurface.texture = NULL;
12690 rsurface.rtlight = NULL;
12691 numsurfacelist = 0;
12692 // add visible surfaces to draw list
12693 for (i = 0;i < model->nummodelsurfaces;i++)
12694 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12695 // don't do anything if there were no surfaces
12696 if (!numsurfacelist)
12698 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12701 // update lightmaps if needed
12705 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12710 R_BuildLightMap(ent, surfaces + j);
12715 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12717 // add to stats if desired
12718 if (r_speeds.integer && !skysurfaces && !depthonly)
12720 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12721 for (j = 0;j < numsurfacelist;j++)
12722 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12725 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12728 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12730 static texture_t texture;
12731 static msurface_t surface;
12732 const msurface_t *surfacelist = &surface;
12734 // fake enough texture and surface state to render this geometry
12736 texture.update_lastrenderframe = -1; // regenerate this texture
12737 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12738 texture.basealpha = 1.0f;
12739 texture.currentskinframe = skinframe;
12740 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12741 texture.offsetmapping = OFFSETMAPPING_OFF;
12742 texture.offsetscale = 1;
12743 texture.specularscalemod = 1;
12744 texture.specularpowermod = 1;
12745 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12746 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12747 // JUST GREP FOR "specularscalemod = 1".
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);
12763 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)
12765 static msurface_t surface;
12766 const msurface_t *surfacelist = &surface;
12768 // fake enough texture and surface state to render this geometry
12769 surface.texture = texture;
12770 surface.num_triangles = numtriangles;
12771 surface.num_firsttriangle = firsttriangle;
12772 surface.num_vertices = numvertices;
12773 surface.num_firstvertex = firstvertex;
12776 rsurface.texture = R_GetCurrentTexture(surface.texture);
12777 rsurface.lightmaptexture = NULL;
12778 rsurface.deluxemaptexture = NULL;
12779 rsurface.uselightmaptexture = false;
12780 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);