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->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) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6009 // store the new plane
6010 planeindex = r_fb.water.numwaterplanes++;
6011 p = r_fb.water.waterplanes + planeindex;
6013 // clear materialflags and pvs
6014 p->materialflags = 0;
6015 p->pvsvalid = false;
6016 p->camera_entity = t->camera_entity;
6017 VectorCopy(mins, p->mins);
6018 VectorCopy(maxs, p->maxs);
6022 // merge mins/maxs when we're adding this surface to the plane
6023 p->mins[0] = min(p->mins[0], mins[0]);
6024 p->mins[1] = min(p->mins[1], mins[1]);
6025 p->mins[2] = min(p->mins[2], mins[2]);
6026 p->maxs[0] = max(p->maxs[0], maxs[0]);
6027 p->maxs[1] = max(p->maxs[1], maxs[1]);
6028 p->maxs[2] = max(p->maxs[2], maxs[2]);
6030 // merge this surface's materialflags into the waterplane
6031 p->materialflags |= t->currentmaterialflags;
6032 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6034 // merge this surface's PVS into the waterplane
6035 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6036 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6038 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6044 extern cvar_t r_drawparticles;
6045 extern cvar_t r_drawdecals;
6047 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6050 r_refdef_view_t originalview;
6051 r_refdef_view_t myview;
6052 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;
6053 r_waterstate_waterplane_t *p;
6055 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;
6058 originalview = r_refdef.view;
6060 // lowquality hack, temporarily shut down some cvars and restore afterwards
6061 qualityreduction = r_water_lowquality.integer;
6062 if (qualityreduction > 0)
6064 if (qualityreduction >= 1)
6066 old_r_shadows = r_shadows.integer;
6067 old_r_worldrtlight = r_shadow_realtime_world.integer;
6068 old_r_dlight = r_shadow_realtime_dlight.integer;
6069 Cvar_SetValueQuick(&r_shadows, 0);
6070 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6071 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6073 if (qualityreduction >= 2)
6075 old_r_dynamic = r_dynamic.integer;
6076 old_r_particles = r_drawparticles.integer;
6077 old_r_decals = r_drawdecals.integer;
6078 Cvar_SetValueQuick(&r_dynamic, 0);
6079 Cvar_SetValueQuick(&r_drawparticles, 0);
6080 Cvar_SetValueQuick(&r_drawdecals, 0);
6084 // make sure enough textures are allocated
6085 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6087 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6089 if (!p->texture_refraction)
6090 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);
6091 if (!p->texture_refraction)
6095 if (r_fb.water.depthtexture == NULL)
6096 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6097 if (p->fbo_refraction == 0)
6098 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6101 else if (p->materialflags & MATERIALFLAG_CAMERA)
6103 if (!p->texture_camera)
6104 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);
6105 if (!p->texture_camera)
6109 if (r_fb.water.depthtexture == NULL)
6110 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6111 if (p->fbo_camera == 0)
6112 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6116 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6118 if (!p->texture_reflection)
6119 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);
6120 if (!p->texture_reflection)
6124 if (r_fb.water.depthtexture == NULL)
6125 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6126 if (p->fbo_reflection == 0)
6127 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6133 r_refdef.view = originalview;
6134 r_refdef.view.showdebug = false;
6135 r_refdef.view.width = r_fb.water.waterwidth;
6136 r_refdef.view.height = r_fb.water.waterheight;
6137 r_refdef.view.useclipplane = true;
6138 myview = r_refdef.view;
6139 r_fb.water.renderingscene = true;
6140 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6142 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6144 r_refdef.view = myview;
6145 if(r_water_scissormode.integer)
6147 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6148 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6149 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6152 // render reflected scene and copy into texture
6153 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6154 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6155 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6156 r_refdef.view.clipplane = p->plane;
6157 // reverse the cullface settings for this render
6158 r_refdef.view.cullface_front = GL_FRONT;
6159 r_refdef.view.cullface_back = GL_BACK;
6160 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6162 r_refdef.view.usecustompvs = true;
6164 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6166 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6169 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6170 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6171 R_ClearScreen(r_refdef.fogenabled);
6172 if(r_water_scissormode.integer & 2)
6173 R_View_UpdateWithScissor(myscissor);
6176 R_AnimCache_CacheVisibleEntities();
6177 if(r_water_scissormode.integer & 1)
6178 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6179 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6181 if (!p->fbo_reflection)
6182 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);
6183 r_fb.water.hideplayer = false;
6186 // render the normal view scene and copy into texture
6187 // (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)
6188 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6190 r_refdef.view = myview;
6191 if(r_water_scissormode.integer)
6193 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6194 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6195 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6198 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6200 r_refdef.view.clipplane = p->plane;
6201 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6202 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6204 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6206 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6207 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6208 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6209 R_RenderView_UpdateViewVectors();
6210 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6212 r_refdef.view.usecustompvs = true;
6213 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);
6217 PlaneClassify(&r_refdef.view.clipplane);
6219 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6220 R_ClearScreen(r_refdef.fogenabled);
6221 if(r_water_scissormode.integer & 2)
6222 R_View_UpdateWithScissor(myscissor);
6225 R_AnimCache_CacheVisibleEntities();
6226 if(r_water_scissormode.integer & 1)
6227 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6228 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6230 if (!p->fbo_refraction)
6231 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);
6232 r_fb.water.hideplayer = false;
6234 else if (p->materialflags & MATERIALFLAG_CAMERA)
6236 r_refdef.view = myview;
6238 r_refdef.view.clipplane = p->plane;
6239 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6240 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6242 r_refdef.view.width = r_fb.water.camerawidth;
6243 r_refdef.view.height = r_fb.water.cameraheight;
6244 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6245 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6246 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6247 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6249 if(p->camera_entity)
6251 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6252 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6255 // note: all of the view is used for displaying... so
6256 // there is no use in scissoring
6258 // reverse the cullface settings for this render
6259 r_refdef.view.cullface_front = GL_FRONT;
6260 r_refdef.view.cullface_back = GL_BACK;
6261 // also reverse the view matrix
6262 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
6263 R_RenderView_UpdateViewVectors();
6264 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6266 r_refdef.view.usecustompvs = true;
6267 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);
6270 // camera needs no clipplane
6271 r_refdef.view.useclipplane = false;
6273 PlaneClassify(&r_refdef.view.clipplane);
6275 r_fb.water.hideplayer = false;
6277 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6278 R_ClearScreen(r_refdef.fogenabled);
6280 R_AnimCache_CacheVisibleEntities();
6281 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6284 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);
6285 r_fb.water.hideplayer = false;
6289 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6290 r_fb.water.renderingscene = false;
6291 r_refdef.view = originalview;
6292 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6293 if (!r_fb.water.depthtexture)
6294 R_ClearScreen(r_refdef.fogenabled);
6296 R_AnimCache_CacheVisibleEntities();
6299 r_refdef.view = originalview;
6300 r_fb.water.renderingscene = false;
6301 Cvar_SetValueQuick(&r_water, 0);
6302 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6304 // lowquality hack, restore cvars
6305 if (qualityreduction > 0)
6307 if (qualityreduction >= 1)
6309 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6310 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6311 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6313 if (qualityreduction >= 2)
6315 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6316 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6317 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6322 static void R_Bloom_StartFrame(void)
6325 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6326 int viewwidth, viewheight;
6327 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6328 textype_t textype = TEXTYPE_COLORBUFFER;
6330 switch (vid.renderpath)
6332 case RENDERPATH_GL20:
6333 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6334 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6336 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6337 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6340 case RENDERPATH_GL11:
6341 case RENDERPATH_GL13:
6342 case RENDERPATH_GLES1:
6343 case RENDERPATH_GLES2:
6344 case RENDERPATH_D3D9:
6345 case RENDERPATH_D3D10:
6346 case RENDERPATH_D3D11:
6347 r_fb.usedepthtextures = false;
6349 case RENDERPATH_SOFT:
6350 r_fb.usedepthtextures = true;
6354 if (r_viewscale_fpsscaling.integer)
6356 double actualframetime;
6357 double targetframetime;
6359 actualframetime = r_refdef.lastdrawscreentime;
6360 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6361 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6362 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6363 if (r_viewscale_fpsscaling_stepsize.value > 0)
6364 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6365 viewscalefpsadjusted += adjust;
6366 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6369 viewscalefpsadjusted = 1.0f;
6371 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6373 switch(vid.renderpath)
6375 case RENDERPATH_GL20:
6376 case RENDERPATH_D3D9:
6377 case RENDERPATH_D3D10:
6378 case RENDERPATH_D3D11:
6379 case RENDERPATH_SOFT:
6380 case RENDERPATH_GLES2:
6382 case RENDERPATH_GL11:
6383 case RENDERPATH_GL13:
6384 case RENDERPATH_GLES1:
6388 // set bloomwidth and bloomheight to the bloom resolution that will be
6389 // used (often less than the screen resolution for faster rendering)
6390 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6391 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6392 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6393 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6394 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6396 // calculate desired texture sizes
6397 if (vid.support.arb_texture_non_power_of_two)
6399 screentexturewidth = vid.width;
6400 screentextureheight = vid.height;
6401 bloomtexturewidth = r_fb.bloomwidth;
6402 bloomtextureheight = r_fb.bloomheight;
6406 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6407 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6408 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6409 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6412 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))
6414 Cvar_SetValueQuick(&r_bloom, 0);
6415 Cvar_SetValueQuick(&r_motionblur, 0);
6416 Cvar_SetValueQuick(&r_damageblur, 0);
6419 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6421 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6423 && r_viewscale.value == 1.0f
6424 && !r_viewscale_fpsscaling.integer)
6425 screentexturewidth = screentextureheight = 0;
6426 if (!r_bloom.integer)
6427 bloomtexturewidth = bloomtextureheight = 0;
6429 // allocate textures as needed
6430 if (r_fb.screentexturewidth != screentexturewidth
6431 || r_fb.screentextureheight != screentextureheight
6432 || r_fb.bloomtexturewidth != bloomtexturewidth
6433 || r_fb.bloomtextureheight != bloomtextureheight
6434 || r_fb.textype != textype
6435 || useviewfbo != (r_fb.fbo != 0))
6437 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6439 if (r_fb.bloomtexture[i])
6440 R_FreeTexture(r_fb.bloomtexture[i]);
6441 r_fb.bloomtexture[i] = NULL;
6443 if (r_fb.bloomfbo[i])
6444 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6445 r_fb.bloomfbo[i] = 0;
6449 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6452 if (r_fb.colortexture)
6453 R_FreeTexture(r_fb.colortexture);
6454 r_fb.colortexture = NULL;
6456 if (r_fb.depthtexture)
6457 R_FreeTexture(r_fb.depthtexture);
6458 r_fb.depthtexture = NULL;
6460 if (r_fb.ghosttexture)
6461 R_FreeTexture(r_fb.ghosttexture);
6462 r_fb.ghosttexture = NULL;
6464 r_fb.screentexturewidth = screentexturewidth;
6465 r_fb.screentextureheight = screentextureheight;
6466 r_fb.bloomtexturewidth = bloomtexturewidth;
6467 r_fb.bloomtextureheight = bloomtextureheight;
6468 r_fb.textype = textype;
6470 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6472 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6473 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);
6474 r_fb.ghosttexture_valid = false;
6475 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);
6478 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6479 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6480 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6484 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6486 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6488 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);
6490 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6495 // bloom texture is a different resolution
6496 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6497 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6498 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6499 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6500 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6502 // set up a texcoord array for the full resolution screen image
6503 // (we have to keep this around to copy back during final render)
6504 r_fb.screentexcoord2f[0] = 0;
6505 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6506 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6507 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6508 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6509 r_fb.screentexcoord2f[5] = 0;
6510 r_fb.screentexcoord2f[6] = 0;
6511 r_fb.screentexcoord2f[7] = 0;
6515 for (i = 1;i < 8;i += 2)
6517 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6521 // set up a texcoord array for the reduced resolution bloom image
6522 // (which will be additive blended over the screen image)
6523 r_fb.bloomtexcoord2f[0] = 0;
6524 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6525 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6526 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6527 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6528 r_fb.bloomtexcoord2f[5] = 0;
6529 r_fb.bloomtexcoord2f[6] = 0;
6530 r_fb.bloomtexcoord2f[7] = 0;
6532 switch(vid.renderpath)
6534 case RENDERPATH_GL11:
6535 case RENDERPATH_GL13:
6536 case RENDERPATH_GL20:
6537 case RENDERPATH_SOFT:
6538 case RENDERPATH_GLES1:
6539 case RENDERPATH_GLES2:
6541 case RENDERPATH_D3D9:
6542 case RENDERPATH_D3D10:
6543 case RENDERPATH_D3D11:
6544 for (i = 0;i < 4;i++)
6546 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6547 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6548 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6549 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6554 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6557 r_refdef.view.clear = true;
6560 static void R_Bloom_MakeTexture(void)
6563 float xoffset, yoffset, r, brighten;
6565 float colorscale = r_bloom_colorscale.value;
6567 r_refdef.stats[r_stat_bloom]++;
6570 // this copy is unnecessary since it happens in R_BlendView already
6573 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);
6574 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6578 // scale down screen texture to the bloom texture size
6580 r_fb.bloomindex = 0;
6581 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6582 R_SetViewport(&r_fb.bloomviewport);
6583 GL_DepthTest(false);
6584 GL_BlendFunc(GL_ONE, GL_ZERO);
6585 GL_Color(colorscale, colorscale, colorscale, 1);
6586 // 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...
6587 switch(vid.renderpath)
6589 case RENDERPATH_GL11:
6590 case RENDERPATH_GL13:
6591 case RENDERPATH_GL20:
6592 case RENDERPATH_GLES1:
6593 case RENDERPATH_GLES2:
6594 case RENDERPATH_SOFT:
6595 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6597 case RENDERPATH_D3D9:
6598 case RENDERPATH_D3D10:
6599 case RENDERPATH_D3D11:
6600 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6603 // TODO: do boxfilter scale-down in shader?
6604 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6605 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6606 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6608 // we now have a properly scaled bloom image
6609 if (!r_fb.bloomfbo[r_fb.bloomindex])
6611 // copy it into the bloom texture
6612 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);
6613 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6616 // multiply bloom image by itself as many times as desired
6617 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6619 intex = r_fb.bloomtexture[r_fb.bloomindex];
6620 r_fb.bloomindex ^= 1;
6621 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6623 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6624 if (!r_fb.bloomfbo[r_fb.bloomindex])
6626 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6627 GL_Color(r,r,r,1); // apply fix factor
6632 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6633 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6634 GL_Color(1,1,1,1); // no fix factor supported here
6636 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6637 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6638 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6639 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6641 if (!r_fb.bloomfbo[r_fb.bloomindex])
6643 // copy the darkened image to a texture
6644 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);
6645 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6649 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6650 brighten = r_bloom_brighten.value;
6651 brighten = sqrt(brighten);
6653 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6655 for (dir = 0;dir < 2;dir++)
6657 intex = r_fb.bloomtexture[r_fb.bloomindex];
6658 r_fb.bloomindex ^= 1;
6659 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6660 // blend on at multiple vertical offsets to achieve a vertical blur
6661 // TODO: do offset blends using GLSL
6662 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6663 GL_BlendFunc(GL_ONE, GL_ZERO);
6664 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6665 for (x = -range;x <= range;x++)
6667 if (!dir){xoffset = 0;yoffset = x;}
6668 else {xoffset = x;yoffset = 0;}
6669 xoffset /= (float)r_fb.bloomtexturewidth;
6670 yoffset /= (float)r_fb.bloomtextureheight;
6671 // compute a texcoord array with the specified x and y offset
6672 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6673 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6674 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6675 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6676 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6677 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6678 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6679 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6680 // this r value looks like a 'dot' particle, fading sharply to
6681 // black at the edges
6682 // (probably not realistic but looks good enough)
6683 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6684 //r = brighten/(range*2+1);
6685 r = brighten / (range * 2 + 1);
6687 r *= (1 - x*x/(float)(range*range));
6688 GL_Color(r, r, r, 1);
6689 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6690 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6691 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6692 GL_BlendFunc(GL_ONE, GL_ONE);
6695 if (!r_fb.bloomfbo[r_fb.bloomindex])
6697 // copy the vertically or horizontally blurred bloom view to a texture
6698 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);
6699 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6704 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6706 unsigned int permutation;
6707 float uservecs[4][4];
6709 R_EntityMatrix(&identitymatrix);
6711 switch (vid.renderpath)
6713 case RENDERPATH_GL20:
6714 case RENDERPATH_D3D9:
6715 case RENDERPATH_D3D10:
6716 case RENDERPATH_D3D11:
6717 case RENDERPATH_SOFT:
6718 case RENDERPATH_GLES2:
6720 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6721 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6722 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6723 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6724 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6726 if (r_fb.colortexture)
6730 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);
6731 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6734 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6736 // declare variables
6737 float blur_factor, blur_mouseaccel, blur_velocity;
6738 static float blur_average;
6739 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6741 // set a goal for the factoring
6742 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6743 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6744 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6745 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6746 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6747 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6749 // from the goal, pick an averaged value between goal and last value
6750 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6751 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6753 // enforce minimum amount of blur
6754 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6756 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6758 // calculate values into a standard alpha
6759 cl.motionbluralpha = 1 - exp(-
6761 (r_motionblur.value * blur_factor / 80)
6763 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6766 max(0.0001, cl.time - cl.oldtime) // fps independent
6769 // randomization for the blur value to combat persistent ghosting
6770 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6771 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6774 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6775 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6777 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6778 GL_Color(1, 1, 1, cl.motionbluralpha);
6779 switch(vid.renderpath)
6781 case RENDERPATH_GL11:
6782 case RENDERPATH_GL13:
6783 case RENDERPATH_GL20:
6784 case RENDERPATH_GLES1:
6785 case RENDERPATH_GLES2:
6786 case RENDERPATH_SOFT:
6787 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6789 case RENDERPATH_D3D9:
6790 case RENDERPATH_D3D10:
6791 case RENDERPATH_D3D11:
6792 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6795 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6796 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6797 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6800 // updates old view angles for next pass
6801 VectorCopy(cl.viewangles, blur_oldangles);
6803 // copy view into the ghost texture
6804 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);
6805 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6806 r_fb.ghosttexture_valid = true;
6811 // no r_fb.colortexture means we're rendering to the real fb
6812 // we may still have to do view tint...
6813 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6815 // apply a color tint to the whole view
6816 R_ResetViewRendering2D(0, NULL, NULL);
6817 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6818 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6819 R_SetupShader_Generic_NoTexture(false, true);
6820 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6821 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6823 break; // no screen processing, no bloom, skip it
6826 if (r_fb.bloomtexture[0])
6828 // make the bloom texture
6829 R_Bloom_MakeTexture();
6832 #if _MSC_VER >= 1400
6833 #define sscanf sscanf_s
6835 memset(uservecs, 0, sizeof(uservecs));
6836 if (r_glsl_postprocess_uservec1_enable.integer)
6837 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6838 if (r_glsl_postprocess_uservec2_enable.integer)
6839 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6840 if (r_glsl_postprocess_uservec3_enable.integer)
6841 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6842 if (r_glsl_postprocess_uservec4_enable.integer)
6843 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6845 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6846 GL_Color(1, 1, 1, 1);
6847 GL_BlendFunc(GL_ONE, GL_ZERO);
6849 switch(vid.renderpath)
6851 case RENDERPATH_GL20:
6852 case RENDERPATH_GLES2:
6853 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6854 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6855 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6856 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6857 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6858 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]);
6859 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6860 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]);
6861 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]);
6862 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]);
6863 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]);
6864 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6865 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6866 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);
6868 case RENDERPATH_D3D9:
6870 // 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...
6871 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6872 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6873 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6874 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6875 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6876 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6877 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6878 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6879 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6880 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6881 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6882 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6883 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6884 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6887 case RENDERPATH_D3D10:
6888 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6890 case RENDERPATH_D3D11:
6891 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6893 case RENDERPATH_SOFT:
6894 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6895 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6896 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6897 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6898 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6899 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6900 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6901 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6902 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6903 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6904 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6905 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6906 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6907 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6912 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6913 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6915 case RENDERPATH_GL11:
6916 case RENDERPATH_GL13:
6917 case RENDERPATH_GLES1:
6918 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6920 // apply a color tint to the whole view
6921 R_ResetViewRendering2D(0, NULL, NULL);
6922 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6923 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6924 R_SetupShader_Generic_NoTexture(false, true);
6925 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6926 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6932 matrix4x4_t r_waterscrollmatrix;
6934 void R_UpdateFog(void)
6937 if (gamemode == GAME_NEHAHRA)
6939 if (gl_fogenable.integer)
6941 r_refdef.oldgl_fogenable = true;
6942 r_refdef.fog_density = gl_fogdensity.value;
6943 r_refdef.fog_red = gl_fogred.value;
6944 r_refdef.fog_green = gl_foggreen.value;
6945 r_refdef.fog_blue = gl_fogblue.value;
6946 r_refdef.fog_alpha = 1;
6947 r_refdef.fog_start = 0;
6948 r_refdef.fog_end = gl_skyclip.value;
6949 r_refdef.fog_height = 1<<30;
6950 r_refdef.fog_fadedepth = 128;
6952 else if (r_refdef.oldgl_fogenable)
6954 r_refdef.oldgl_fogenable = false;
6955 r_refdef.fog_density = 0;
6956 r_refdef.fog_red = 0;
6957 r_refdef.fog_green = 0;
6958 r_refdef.fog_blue = 0;
6959 r_refdef.fog_alpha = 0;
6960 r_refdef.fog_start = 0;
6961 r_refdef.fog_end = 0;
6962 r_refdef.fog_height = 1<<30;
6963 r_refdef.fog_fadedepth = 128;
6968 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6969 r_refdef.fog_start = max(0, r_refdef.fog_start);
6970 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6972 if (r_refdef.fog_density && r_drawfog.integer)
6974 r_refdef.fogenabled = true;
6975 // this is the point where the fog reaches 0.9986 alpha, which we
6976 // consider a good enough cutoff point for the texture
6977 // (0.9986 * 256 == 255.6)
6978 if (r_fog_exp2.integer)
6979 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6981 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6982 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6983 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6984 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6985 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6986 R_BuildFogHeightTexture();
6987 // fog color was already set
6988 // update the fog texture
6989 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)
6990 R_BuildFogTexture();
6991 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6992 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6995 r_refdef.fogenabled = false;
6998 if (r_refdef.fog_density)
7000 r_refdef.fogcolor[0] = r_refdef.fog_red;
7001 r_refdef.fogcolor[1] = r_refdef.fog_green;
7002 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7004 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7005 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7006 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7007 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7011 VectorCopy(r_refdef.fogcolor, fogvec);
7012 // color.rgb *= ContrastBoost * SceneBrightness;
7013 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7014 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7015 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7016 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7021 void R_UpdateVariables(void)
7025 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7027 r_refdef.farclip = r_farclip_base.value;
7028 if (r_refdef.scene.worldmodel)
7029 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7030 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7032 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7033 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7034 r_refdef.polygonfactor = 0;
7035 r_refdef.polygonoffset = 0;
7036 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7037 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7039 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7040 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7041 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7042 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7043 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7044 if (FAKELIGHT_ENABLED)
7046 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7048 else if (r_refdef.scene.worldmodel)
7050 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7052 if (r_showsurfaces.integer)
7054 r_refdef.scene.rtworld = false;
7055 r_refdef.scene.rtworldshadows = false;
7056 r_refdef.scene.rtdlight = false;
7057 r_refdef.scene.rtdlightshadows = false;
7058 r_refdef.lightmapintensity = 0;
7061 r_gpuskeletal = false;
7062 switch(vid.renderpath)
7064 case RENDERPATH_GL20:
7065 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7066 case RENDERPATH_D3D9:
7067 case RENDERPATH_D3D10:
7068 case RENDERPATH_D3D11:
7069 case RENDERPATH_SOFT:
7070 case RENDERPATH_GLES2:
7071 if(v_glslgamma.integer && !vid_gammatables_trivial)
7073 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7075 // build GLSL gamma texture
7076 #define RAMPWIDTH 256
7077 unsigned short ramp[RAMPWIDTH * 3];
7078 unsigned char rampbgr[RAMPWIDTH][4];
7081 r_texture_gammaramps_serial = vid_gammatables_serial;
7083 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7084 for(i = 0; i < RAMPWIDTH; ++i)
7086 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7087 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7088 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7091 if (r_texture_gammaramps)
7093 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7097 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7103 // remove GLSL gamma texture
7106 case RENDERPATH_GL11:
7107 case RENDERPATH_GL13:
7108 case RENDERPATH_GLES1:
7113 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7114 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7120 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7121 if( scenetype != r_currentscenetype ) {
7122 // store the old scenetype
7123 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7124 r_currentscenetype = scenetype;
7125 // move in the new scene
7126 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7135 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7137 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7138 if( scenetype == r_currentscenetype ) {
7139 return &r_refdef.scene;
7141 return &r_scenes_store[ scenetype ];
7145 static int R_SortEntities_Compare(const void *ap, const void *bp)
7147 const entity_render_t *a = *(const entity_render_t **)ap;
7148 const entity_render_t *b = *(const entity_render_t **)bp;
7151 if(a->model < b->model)
7153 if(a->model > b->model)
7157 // TODO possibly calculate the REAL skinnum here first using
7159 if(a->skinnum < b->skinnum)
7161 if(a->skinnum > b->skinnum)
7164 // everything we compared is equal
7167 static void R_SortEntities(void)
7169 // below or equal 2 ents, sorting never gains anything
7170 if(r_refdef.scene.numentities <= 2)
7173 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7181 int dpsoftrast_test;
7182 extern cvar_t r_shadow_bouncegrid;
7183 void R_RenderView(void)
7185 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7187 rtexture_t *depthtexture;
7188 rtexture_t *colortexture;
7190 dpsoftrast_test = r_test.integer;
7192 if (r_timereport_active)
7193 R_TimeReport("start");
7194 r_textureframe++; // used only by R_GetCurrentTexture
7195 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7197 if(R_CompileShader_CheckStaticParms())
7200 if (!r_drawentities.integer)
7201 r_refdef.scene.numentities = 0;
7202 else if (r_sortentities.integer)
7205 R_AnimCache_ClearCache();
7207 /* adjust for stereo display */
7208 if(R_Stereo_Active())
7210 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
7211 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7214 if (r_refdef.view.isoverlay)
7216 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7217 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7218 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7219 R_TimeReport("depthclear");
7221 r_refdef.view.showdebug = false;
7223 r_fb.water.enabled = false;
7224 r_fb.water.numwaterplanes = 0;
7226 R_RenderScene(0, NULL, NULL);
7228 r_refdef.view.matrix = originalmatrix;
7234 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7236 r_refdef.view.matrix = originalmatrix;
7240 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7242 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7243 // in sRGB fallback, behave similar to true sRGB: convert this
7244 // value from linear to sRGB
7245 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7247 R_RenderView_UpdateViewVectors();
7249 R_Shadow_UpdateWorldLightSelection();
7251 R_Bloom_StartFrame();
7253 // apply bloom brightness offset
7254 if(r_fb.bloomtexture[0])
7255 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7257 R_Water_StartFrame();
7259 // now we probably have an fbo to render into
7261 depthtexture = r_fb.depthtexture;
7262 colortexture = r_fb.colortexture;
7265 if (r_timereport_active)
7266 R_TimeReport("viewsetup");
7268 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7270 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7272 R_ClearScreen(r_refdef.fogenabled);
7273 if (r_timereport_active)
7274 R_TimeReport("viewclear");
7276 r_refdef.view.clear = true;
7278 r_refdef.view.showdebug = true;
7281 if (r_timereport_active)
7282 R_TimeReport("visibility");
7284 R_AnimCache_CacheVisibleEntities();
7285 if (r_timereport_active)
7286 R_TimeReport("animcache");
7288 R_Shadow_UpdateBounceGridTexture();
7289 if (r_timereport_active && r_shadow_bouncegrid.integer)
7290 R_TimeReport("bouncegrid");
7292 r_fb.water.numwaterplanes = 0;
7293 if (r_fb.water.enabled)
7294 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7296 R_RenderScene(fbo, depthtexture, colortexture);
7297 r_fb.water.numwaterplanes = 0;
7299 R_BlendView(fbo, depthtexture, colortexture);
7300 if (r_timereport_active)
7301 R_TimeReport("blendview");
7303 GL_Scissor(0, 0, vid.width, vid.height);
7304 GL_ScissorTest(false);
7306 r_refdef.view.matrix = originalmatrix;
7311 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7313 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7315 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7316 if (r_timereport_active)
7317 R_TimeReport("waterworld");
7320 // don't let sound skip if going slow
7321 if (r_refdef.scene.extraupdate)
7324 R_DrawModelsAddWaterPlanes();
7325 if (r_timereport_active)
7326 R_TimeReport("watermodels");
7328 if (r_fb.water.numwaterplanes)
7330 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7331 if (r_timereport_active)
7332 R_TimeReport("waterscenes");
7336 extern cvar_t cl_locs_show;
7337 static void R_DrawLocs(void);
7338 static void R_DrawEntityBBoxes(void);
7339 static void R_DrawModelDecals(void);
7340 extern cvar_t cl_decals_newsystem;
7341 extern qboolean r_shadow_usingdeferredprepass;
7342 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7344 qboolean shadowmapping = false;
7346 if (r_timereport_active)
7347 R_TimeReport("beginscene");
7349 r_refdef.stats[r_stat_renders]++;
7353 // don't let sound skip if going slow
7354 if (r_refdef.scene.extraupdate)
7357 R_MeshQueue_BeginScene();
7361 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
7363 if (r_timereport_active)
7364 R_TimeReport("skystartframe");
7366 if (cl.csqc_vidvars.drawworld)
7368 // don't let sound skip if going slow
7369 if (r_refdef.scene.extraupdate)
7372 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7374 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7375 if (r_timereport_active)
7376 R_TimeReport("worldsky");
7379 if (R_DrawBrushModelsSky() && r_timereport_active)
7380 R_TimeReport("bmodelsky");
7382 if (skyrendermasked && skyrenderlater)
7384 // we have to force off the water clipping plane while rendering sky
7385 R_SetupView(false, fbo, depthtexture, colortexture);
7387 R_SetupView(true, fbo, depthtexture, colortexture);
7388 if (r_timereport_active)
7389 R_TimeReport("sky");
7393 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7394 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7395 R_Shadow_PrepareModelShadows();
7396 if (r_timereport_active)
7397 R_TimeReport("preparelights");
7399 if (R_Shadow_ShadowMappingEnabled())
7400 shadowmapping = true;
7402 if (r_shadow_usingdeferredprepass)
7403 R_Shadow_DrawPrepass();
7405 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7407 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7408 if (r_timereport_active)
7409 R_TimeReport("worlddepth");
7411 if (r_depthfirst.integer >= 2)
7413 R_DrawModelsDepth();
7414 if (r_timereport_active)
7415 R_TimeReport("modeldepth");
7418 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7420 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7421 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7422 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7423 // don't let sound skip if going slow
7424 if (r_refdef.scene.extraupdate)
7428 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7430 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7431 if (r_timereport_active)
7432 R_TimeReport("world");
7435 // don't let sound skip if going slow
7436 if (r_refdef.scene.extraupdate)
7440 if (r_timereport_active)
7441 R_TimeReport("models");
7443 // don't let sound skip if going slow
7444 if (r_refdef.scene.extraupdate)
7447 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7449 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7450 R_DrawModelShadows(fbo, depthtexture, colortexture);
7451 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7452 // don't let sound skip if going slow
7453 if (r_refdef.scene.extraupdate)
7457 if (!r_shadow_usingdeferredprepass)
7459 R_Shadow_DrawLights();
7460 if (r_timereport_active)
7461 R_TimeReport("rtlights");
7464 // don't let sound skip if going slow
7465 if (r_refdef.scene.extraupdate)
7468 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7470 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7471 R_DrawModelShadows(fbo, depthtexture, colortexture);
7472 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7473 // don't let sound skip if going slow
7474 if (r_refdef.scene.extraupdate)
7478 if (cl.csqc_vidvars.drawworld)
7480 if (cl_decals_newsystem.integer)
7482 R_DrawModelDecals();
7483 if (r_timereport_active)
7484 R_TimeReport("modeldecals");
7489 if (r_timereport_active)
7490 R_TimeReport("decals");
7494 if (r_timereport_active)
7495 R_TimeReport("particles");
7498 if (r_timereport_active)
7499 R_TimeReport("explosions");
7501 R_DrawLightningBeams();
7502 if (r_timereport_active)
7503 R_TimeReport("lightning");
7507 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7509 if (r_refdef.view.showdebug)
7511 if (cl_locs_show.integer)
7514 if (r_timereport_active)
7515 R_TimeReport("showlocs");
7518 if (r_drawportals.integer)
7521 if (r_timereport_active)
7522 R_TimeReport("portals");
7525 if (r_showbboxes.value > 0)
7527 R_DrawEntityBBoxes();
7528 if (r_timereport_active)
7529 R_TimeReport("bboxes");
7533 if (r_transparent.integer)
7535 R_MeshQueue_RenderTransparent();
7536 if (r_timereport_active)
7537 R_TimeReport("drawtrans");
7540 if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0 || r_showoverdraw.value > 0))
7542 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7543 if (r_timereport_active)
7544 R_TimeReport("worlddebug");
7545 R_DrawModelsDebug();
7546 if (r_timereport_active)
7547 R_TimeReport("modeldebug");
7550 if (cl.csqc_vidvars.drawworld)
7552 R_Shadow_DrawCoronas();
7553 if (r_timereport_active)
7554 R_TimeReport("coronas");
7559 GL_DepthTest(false);
7560 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7561 GL_Color(1, 1, 1, 1);
7562 qglBegin(GL_POLYGON);
7563 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7564 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7565 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7566 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7568 qglBegin(GL_POLYGON);
7569 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
7570 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
7571 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
7572 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
7574 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7578 // don't let sound skip if going slow
7579 if (r_refdef.scene.extraupdate)
7583 static const unsigned short bboxelements[36] =
7593 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7596 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7598 RSurf_ActiveWorldEntity();
7600 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7601 GL_DepthMask(false);
7602 GL_DepthRange(0, 1);
7603 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7604 // R_Mesh_ResetTextureState();
7606 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7607 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7608 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7609 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7610 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7611 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7612 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7613 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7614 R_FillColors(color4f, 8, cr, cg, cb, ca);
7615 if (r_refdef.fogenabled)
7617 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7619 f1 = RSurf_FogVertex(v);
7621 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7622 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7623 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7626 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7627 R_Mesh_ResetTextureState();
7628 R_SetupShader_Generic_NoTexture(false, false);
7629 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7632 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7634 prvm_prog_t *prog = SVVM_prog;
7637 prvm_edict_t *edict;
7639 // this function draws bounding boxes of server entities
7643 GL_CullFace(GL_NONE);
7644 R_SetupShader_Generic_NoTexture(false, false);
7646 for (i = 0;i < numsurfaces;i++)
7648 edict = PRVM_EDICT_NUM(surfacelist[i]);
7649 switch ((int)PRVM_serveredictfloat(edict, solid))
7651 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7652 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7653 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7654 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7655 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7656 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7657 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7659 color[3] *= r_showbboxes.value;
7660 color[3] = bound(0, color[3], 1);
7661 GL_DepthTest(!r_showdisabledepthtest.integer);
7662 GL_CullFace(r_refdef.view.cullface_front);
7663 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7667 static void R_DrawEntityBBoxes(void)
7670 prvm_edict_t *edict;
7672 prvm_prog_t *prog = SVVM_prog;
7674 // this function draws bounding boxes of server entities
7678 for (i = 0;i < prog->num_edicts;i++)
7680 edict = PRVM_EDICT_NUM(i);
7681 if (edict->priv.server->free)
7683 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7684 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7686 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7688 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7689 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7693 static const int nomodelelement3i[24] =
7705 static const unsigned short nomodelelement3s[24] =
7717 static const float nomodelvertex3f[6*3] =
7727 static const float nomodelcolor4f[6*4] =
7729 0.0f, 0.0f, 0.5f, 1.0f,
7730 0.0f, 0.0f, 0.5f, 1.0f,
7731 0.0f, 0.5f, 0.0f, 1.0f,
7732 0.0f, 0.5f, 0.0f, 1.0f,
7733 0.5f, 0.0f, 0.0f, 1.0f,
7734 0.5f, 0.0f, 0.0f, 1.0f
7737 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7743 RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7745 // this is only called once per entity so numsurfaces is always 1, and
7746 // surfacelist is always {0}, so this code does not handle batches
7748 if (rsurface.ent_flags & RENDER_ADDITIVE)
7750 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7751 GL_DepthMask(false);
7753 else if (rsurface.colormod[3] < 1)
7755 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7756 GL_DepthMask(false);
7760 GL_BlendFunc(GL_ONE, GL_ZERO);
7763 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7764 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7765 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7766 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7767 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7768 for (i = 0, c = color4f;i < 6;i++, c += 4)
7770 c[0] *= rsurface.colormod[0];
7771 c[1] *= rsurface.colormod[1];
7772 c[2] *= rsurface.colormod[2];
7773 c[3] *= rsurface.colormod[3];
7775 if (r_refdef.fogenabled)
7777 for (i = 0, c = color4f;i < 6;i++, c += 4)
7779 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7781 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7782 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7783 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7786 // R_Mesh_ResetTextureState();
7787 R_SetupShader_Generic_NoTexture(false, false);
7788 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7789 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7792 void R_DrawNoModel(entity_render_t *ent)
7795 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7796 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7797 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7799 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7802 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7804 vec3_t right1, right2, diff, normal;
7806 VectorSubtract (org2, org1, normal);
7808 // calculate 'right' vector for start
7809 VectorSubtract (r_refdef.view.origin, org1, diff);
7810 CrossProduct (normal, diff, right1);
7811 VectorNormalize (right1);
7813 // calculate 'right' vector for end
7814 VectorSubtract (r_refdef.view.origin, org2, diff);
7815 CrossProduct (normal, diff, right2);
7816 VectorNormalize (right2);
7818 vert[ 0] = org1[0] + width * right1[0];
7819 vert[ 1] = org1[1] + width * right1[1];
7820 vert[ 2] = org1[2] + width * right1[2];
7821 vert[ 3] = org1[0] - width * right1[0];
7822 vert[ 4] = org1[1] - width * right1[1];
7823 vert[ 5] = org1[2] - width * right1[2];
7824 vert[ 6] = org2[0] - width * right2[0];
7825 vert[ 7] = org2[1] - width * right2[1];
7826 vert[ 8] = org2[2] - width * right2[2];
7827 vert[ 9] = org2[0] + width * right2[0];
7828 vert[10] = org2[1] + width * right2[1];
7829 vert[11] = org2[2] + width * right2[2];
7832 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
7834 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7835 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7836 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7837 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7838 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7839 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7840 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7841 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7842 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7843 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7844 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7845 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7848 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7853 VectorSet(v, x, y, z);
7854 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7855 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7857 if (i == mesh->numvertices)
7859 if (mesh->numvertices < mesh->maxvertices)
7861 VectorCopy(v, vertex3f);
7862 mesh->numvertices++;
7864 return mesh->numvertices;
7870 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7874 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7875 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7876 e = mesh->element3i + mesh->numtriangles * 3;
7877 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7879 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7880 if (mesh->numtriangles < mesh->maxtriangles)
7885 mesh->numtriangles++;
7887 element[1] = element[2];
7891 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7895 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7896 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7897 e = mesh->element3i + mesh->numtriangles * 3;
7898 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7900 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7901 if (mesh->numtriangles < mesh->maxtriangles)
7906 mesh->numtriangles++;
7908 element[1] = element[2];
7912 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7913 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7915 int planenum, planenum2;
7918 mplane_t *plane, *plane2;
7920 double temppoints[2][256*3];
7921 // figure out how large a bounding box we need to properly compute this brush
7923 for (w = 0;w < numplanes;w++)
7924 maxdist = max(maxdist, fabs(planes[w].dist));
7925 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7926 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7927 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7931 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7932 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7934 if (planenum2 == planenum)
7936 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
7939 if (tempnumpoints < 3)
7941 // generate elements forming a triangle fan for this polygon
7942 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7946 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7948 texturelayer_t *layer;
7949 layer = t->currentlayers + t->currentnumlayers++;
7951 layer->depthmask = depthmask;
7952 layer->blendfunc1 = blendfunc1;
7953 layer->blendfunc2 = blendfunc2;
7954 layer->texture = texture;
7955 layer->texmatrix = *matrix;
7956 layer->color[0] = r;
7957 layer->color[1] = g;
7958 layer->color[2] = b;
7959 layer->color[3] = a;
7962 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7964 if(parms[0] == 0 && parms[1] == 0)
7966 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7967 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7972 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7975 index = parms[2] + rsurface.shadertime * parms[3];
7976 index -= floor(index);
7977 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7980 case Q3WAVEFUNC_NONE:
7981 case Q3WAVEFUNC_NOISE:
7982 case Q3WAVEFUNC_COUNT:
7985 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7986 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7987 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7988 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7989 case Q3WAVEFUNC_TRIANGLE:
7991 f = index - floor(index);
8004 f = parms[0] + parms[1] * f;
8005 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8006 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8010 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8017 matrix4x4_t matrix, temp;
8018 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8019 // it's better to have one huge fixup every 9 hours than gradual
8020 // degradation over time which looks consistently bad after many hours.
8022 // tcmod scroll in particular suffers from this degradation which can't be
8023 // effectively worked around even with floor() tricks because we don't
8024 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8025 // a workaround involving floor() would be incorrect anyway...
8026 shadertime = rsurface.shadertime;
8027 if (shadertime >= 32768.0f)
8028 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8029 switch(tcmod->tcmod)
8033 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8034 matrix = r_waterscrollmatrix;
8036 matrix = identitymatrix;
8038 case Q3TCMOD_ENTITYTRANSLATE:
8039 // this is used in Q3 to allow the gamecode to control texcoord
8040 // scrolling on the entity, which is not supported in darkplaces yet.
8041 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8043 case Q3TCMOD_ROTATE:
8044 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8045 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8046 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8049 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8051 case Q3TCMOD_SCROLL:
8052 // this particular tcmod is a "bug for bug" compatible one with regards to
8053 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8054 // specifically did the wrapping and so we must mimic that...
8055 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8056 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8057 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8059 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8060 w = (int) tcmod->parms[0];
8061 h = (int) tcmod->parms[1];
8062 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8064 idx = (int) floor(f * w * h);
8065 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8067 case Q3TCMOD_STRETCH:
8068 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8069 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8071 case Q3TCMOD_TRANSFORM:
8072 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8073 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8074 VectorSet(tcmat + 6, 0 , 0 , 1);
8075 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8076 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8078 case Q3TCMOD_TURBULENT:
8079 // this is handled in the RSurf_PrepareVertices function
8080 matrix = identitymatrix;
8084 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8087 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8089 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8090 char name[MAX_QPATH];
8091 skinframe_t *skinframe;
8092 unsigned char pixels[296*194];
8093 strlcpy(cache->name, skinname, sizeof(cache->name));
8094 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8095 if (developer_loading.integer)
8096 Con_Printf("loading %s\n", name);
8097 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8098 if (!skinframe || !skinframe->base)
8101 fs_offset_t filesize;
8103 f = FS_LoadFile(name, tempmempool, true, &filesize);
8106 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8107 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8111 cache->skinframe = skinframe;
8114 texture_t *R_GetCurrentTexture(texture_t *t)
8117 const entity_render_t *ent = rsurface.entity;
8118 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8119 q3shaderinfo_layer_tcmod_t *tcmod;
8121 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8122 return t->currentframe;
8123 t->update_lastrenderframe = r_textureframe;
8124 t->update_lastrenderentity = (void *)ent;
8126 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8127 t->camera_entity = ent->entitynumber;
8129 t->camera_entity = 0;
8131 // switch to an alternate material if this is a q1bsp animated material
8133 texture_t *texture = t;
8134 int s = rsurface.ent_skinnum;
8135 if ((unsigned int)s >= (unsigned int)model->numskins)
8137 if (model->skinscenes)
8139 if (model->skinscenes[s].framecount > 1)
8140 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8142 s = model->skinscenes[s].firstframe;
8145 t = t + s * model->num_surfaces;
8148 // use an alternate animation if the entity's frame is not 0,
8149 // and only if the texture has an alternate animation
8150 if (t->animated == 2) // q2bsp
8151 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8152 else if (rsurface.ent_alttextures && t->anim_total[1])
8153 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8155 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8157 texture->currentframe = t;
8160 // update currentskinframe to be a qw skin or animation frame
8161 if (rsurface.ent_qwskin >= 0)
8163 i = rsurface.ent_qwskin;
8164 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8166 r_qwskincache_size = cl.maxclients;
8168 Mem_Free(r_qwskincache);
8169 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8171 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8172 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8173 t->currentskinframe = r_qwskincache[i].skinframe;
8174 if (t->currentskinframe == NULL)
8175 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8177 else if (t->numskinframes >= 2)
8178 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8179 if (t->backgroundnumskinframes >= 2)
8180 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8182 t->currentmaterialflags = t->basematerialflags;
8183 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8184 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8185 t->currentalpha *= r_wateralpha.value;
8186 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8187 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8188 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8189 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8190 if (!(rsurface.ent_flags & RENDER_LIGHT))
8191 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8192 else if (FAKELIGHT_ENABLED)
8194 // no modellight if using fakelight for the map
8196 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8198 // pick a model lighting mode
8199 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8200 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8202 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8204 if (rsurface.ent_flags & RENDER_ADDITIVE)
8205 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8206 else if (t->currentalpha < 1)
8207 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8208 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8209 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8210 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8211 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8212 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8213 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8214 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8215 if (t->backgroundnumskinframes)
8216 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8217 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8219 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8220 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8223 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8224 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8226 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8227 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8229 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8230 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8232 // there is no tcmod
8233 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8235 t->currenttexmatrix = r_waterscrollmatrix;
8236 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8238 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8240 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8241 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8244 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8245 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8246 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8247 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8249 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8250 if (t->currentskinframe->qpixels)
8251 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8252 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8253 if (!t->basetexture)
8254 t->basetexture = r_texture_notexture;
8255 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8256 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8257 t->nmaptexture = t->currentskinframe->nmap;
8258 if (!t->nmaptexture)
8259 t->nmaptexture = r_texture_blanknormalmap;
8260 t->glosstexture = r_texture_black;
8261 t->glowtexture = t->currentskinframe->glow;
8262 t->fogtexture = t->currentskinframe->fog;
8263 t->reflectmasktexture = t->currentskinframe->reflect;
8264 if (t->backgroundnumskinframes)
8266 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8267 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8268 t->backgroundglosstexture = r_texture_black;
8269 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8270 if (!t->backgroundnmaptexture)
8271 t->backgroundnmaptexture = r_texture_blanknormalmap;
8272 // make sure that if glow is going to be used, both textures are not NULL
8273 if (!t->backgroundglowtexture && t->glowtexture)
8274 t->backgroundglowtexture = r_texture_black;
8275 if (!t->glowtexture && t->backgroundglowtexture)
8276 t->glowtexture = r_texture_black;
8280 t->backgroundbasetexture = r_texture_white;
8281 t->backgroundnmaptexture = r_texture_blanknormalmap;
8282 t->backgroundglosstexture = r_texture_black;
8283 t->backgroundglowtexture = NULL;
8285 t->specularpower = r_shadow_glossexponent.value;
8286 // TODO: store reference values for these in the texture?
8287 t->specularscale = 0;
8288 if (r_shadow_gloss.integer > 0)
8290 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8292 if (r_shadow_glossintensity.value > 0)
8294 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8295 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8296 t->specularscale = r_shadow_glossintensity.value;
8299 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8301 t->glosstexture = r_texture_white;
8302 t->backgroundglosstexture = r_texture_white;
8303 t->specularscale = r_shadow_gloss2intensity.value;
8304 t->specularpower = r_shadow_gloss2exponent.value;
8307 t->specularscale *= t->specularscalemod;
8308 t->specularpower *= t->specularpowermod;
8309 t->rtlightambient = 0;
8311 // lightmaps mode looks bad with dlights using actual texturing, so turn
8312 // off the colormap and glossmap, but leave the normalmap on as it still
8313 // accurately represents the shading involved
8314 if (gl_lightmaps.integer)
8316 t->basetexture = r_texture_grey128;
8317 t->pantstexture = r_texture_black;
8318 t->shirttexture = r_texture_black;
8319 if (gl_lightmaps.integer < 2)
8320 t->nmaptexture = r_texture_blanknormalmap;
8321 t->glosstexture = r_texture_black;
8322 t->glowtexture = NULL;
8323 t->fogtexture = NULL;
8324 t->reflectmasktexture = NULL;
8325 t->backgroundbasetexture = NULL;
8326 if (gl_lightmaps.integer < 2)
8327 t->backgroundnmaptexture = r_texture_blanknormalmap;
8328 t->backgroundglosstexture = r_texture_black;
8329 t->backgroundglowtexture = NULL;
8330 t->specularscale = 0;
8331 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8334 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8335 VectorClear(t->dlightcolor);
8336 t->currentnumlayers = 0;
8337 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8339 int blendfunc1, blendfunc2;
8341 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8343 blendfunc1 = GL_SRC_ALPHA;
8344 blendfunc2 = GL_ONE;
8346 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8348 blendfunc1 = GL_SRC_ALPHA;
8349 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8351 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8353 blendfunc1 = t->customblendfunc[0];
8354 blendfunc2 = t->customblendfunc[1];
8358 blendfunc1 = GL_ONE;
8359 blendfunc2 = GL_ZERO;
8361 // don't colormod evilblend textures
8362 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8363 VectorSet(t->lightmapcolor, 1, 1, 1);
8364 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8365 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8367 // fullbright is not affected by r_refdef.lightmapintensity
8368 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]);
8369 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8370 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]);
8371 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8372 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]);
8376 vec3_t ambientcolor;
8378 // set the color tint used for lights affecting this surface
8379 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8381 // q3bsp has no lightmap updates, so the lightstylevalue that
8382 // would normally be baked into the lightmap must be
8383 // applied to the color
8384 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8385 if (model->type == mod_brushq3)
8386 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8387 colorscale *= r_refdef.lightmapintensity;
8388 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8389 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8390 // basic lit geometry
8391 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]);
8392 // add pants/shirt if needed
8393 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8394 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]);
8395 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8396 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]);
8397 // now add ambient passes if needed
8398 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8400 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]);
8401 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8402 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]);
8403 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8404 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]);
8407 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8408 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]);
8409 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8411 // if this is opaque use alpha blend which will darken the earlier
8414 // if this is an alpha blended material, all the earlier passes
8415 // were darkened by fog already, so we only need to add the fog
8416 // color ontop through the fog mask texture
8418 // if this is an additive blended material, all the earlier passes
8419 // were darkened by fog already, and we should not add fog color
8420 // (because the background was not darkened, there is no fog color
8421 // that was lost behind it).
8422 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]);
8426 return t->currentframe;
8429 rsurfacestate_t rsurface;
8431 void RSurf_ActiveWorldEntity(void)
8433 dp_model_t *model = r_refdef.scene.worldmodel;
8434 //if (rsurface.entity == r_refdef.scene.worldentity)
8436 rsurface.entity = r_refdef.scene.worldentity;
8437 rsurface.skeleton = NULL;
8438 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8439 rsurface.ent_skinnum = 0;
8440 rsurface.ent_qwskin = -1;
8441 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8442 rsurface.shadertime = r_refdef.scene.time;
8443 rsurface.matrix = identitymatrix;
8444 rsurface.inversematrix = identitymatrix;
8445 rsurface.matrixscale = 1;
8446 rsurface.inversematrixscale = 1;
8447 R_EntityMatrix(&identitymatrix);
8448 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8449 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8450 rsurface.fograngerecip = r_refdef.fograngerecip;
8451 rsurface.fogheightfade = r_refdef.fogheightfade;
8452 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8453 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8454 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8455 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8456 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8457 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8458 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8459 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8460 rsurface.colormod[3] = 1;
8461 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);
8462 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8463 rsurface.frameblend[0].lerp = 1;
8464 rsurface.ent_alttextures = false;
8465 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8466 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8467 rsurface.entityskeletaltransform3x4 = NULL;
8468 rsurface.entityskeletaltransform3x4buffer = NULL;
8469 rsurface.entityskeletaltransform3x4offset = 0;
8470 rsurface.entityskeletaltransform3x4size = 0;;
8471 rsurface.entityskeletalnumtransforms = 0;
8472 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8473 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8475 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8476 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8477 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8478 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8479 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8480 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8481 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8482 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8484 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8485 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8486 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8487 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8488 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8489 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8490 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8491 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8492 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8493 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8494 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8495 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8496 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8497 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8498 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8499 rsurface.modelelement3i = model->surfmesh.data_element3i;
8500 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8501 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8502 rsurface.modelelement3s = model->surfmesh.data_element3s;
8503 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8504 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8505 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8506 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8507 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8508 rsurface.modelsurfaces = model->data_surfaces;
8509 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8510 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8511 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8512 rsurface.modelgeneratedvertex = false;
8513 rsurface.batchgeneratedvertex = false;
8514 rsurface.batchfirstvertex = 0;
8515 rsurface.batchnumvertices = 0;
8516 rsurface.batchfirsttriangle = 0;
8517 rsurface.batchnumtriangles = 0;
8518 rsurface.batchvertex3f = NULL;
8519 rsurface.batchvertex3f_vertexbuffer = NULL;
8520 rsurface.batchvertex3f_bufferoffset = 0;
8521 rsurface.batchsvector3f = NULL;
8522 rsurface.batchsvector3f_vertexbuffer = NULL;
8523 rsurface.batchsvector3f_bufferoffset = 0;
8524 rsurface.batchtvector3f = NULL;
8525 rsurface.batchtvector3f_vertexbuffer = NULL;
8526 rsurface.batchtvector3f_bufferoffset = 0;
8527 rsurface.batchnormal3f = NULL;
8528 rsurface.batchnormal3f_vertexbuffer = NULL;
8529 rsurface.batchnormal3f_bufferoffset = 0;
8530 rsurface.batchlightmapcolor4f = NULL;
8531 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8532 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8533 rsurface.batchtexcoordtexture2f = NULL;
8534 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8535 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8536 rsurface.batchtexcoordlightmap2f = NULL;
8537 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8538 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8539 rsurface.batchskeletalindex4ub = NULL;
8540 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8541 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8542 rsurface.batchskeletalweight4ub = NULL;
8543 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8544 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8545 rsurface.batchvertexmesh = NULL;
8546 rsurface.batchvertexmesh_vertexbuffer = NULL;
8547 rsurface.batchvertexmesh_bufferoffset = 0;
8548 rsurface.batchelement3i = NULL;
8549 rsurface.batchelement3i_indexbuffer = NULL;
8550 rsurface.batchelement3i_bufferoffset = 0;
8551 rsurface.batchelement3s = NULL;
8552 rsurface.batchelement3s_indexbuffer = NULL;
8553 rsurface.batchelement3s_bufferoffset = 0;
8554 rsurface.passcolor4f = NULL;
8555 rsurface.passcolor4f_vertexbuffer = NULL;
8556 rsurface.passcolor4f_bufferoffset = 0;
8557 rsurface.forcecurrenttextureupdate = false;
8560 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8562 dp_model_t *model = ent->model;
8563 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8565 rsurface.entity = (entity_render_t *)ent;
8566 rsurface.skeleton = ent->skeleton;
8567 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8568 rsurface.ent_skinnum = ent->skinnum;
8569 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;
8570 rsurface.ent_flags = ent->flags;
8571 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8572 rsurface.matrix = ent->matrix;
8573 rsurface.inversematrix = ent->inversematrix;
8574 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8575 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8576 R_EntityMatrix(&rsurface.matrix);
8577 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8578 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8579 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8580 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8581 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8582 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8583 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8584 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8585 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8586 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8587 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8588 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8589 rsurface.colormod[3] = ent->alpha;
8590 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8591 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8592 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8593 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8594 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8595 if (ent->model->brush.submodel && !prepass)
8597 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8598 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8600 // if the animcache code decided it should use the shader path, skip the deform step
8601 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8602 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8603 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8604 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8605 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8606 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8608 if (ent->animcache_vertex3f)
8610 r_refdef.stats[r_stat_batch_entitycache_count]++;
8611 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8612 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8613 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8614 rsurface.modelvertex3f = ent->animcache_vertex3f;
8615 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8616 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8617 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8618 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8619 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8620 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8621 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8622 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8623 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8624 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8625 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8626 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8627 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8628 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8630 else if (wanttangents)
8632 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8633 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8634 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8635 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8636 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8637 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8638 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8639 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8640 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8641 rsurface.modelvertexmesh = NULL;
8642 rsurface.modelvertexmesh_vertexbuffer = NULL;
8643 rsurface.modelvertexmesh_bufferoffset = 0;
8644 rsurface.modelvertex3f_vertexbuffer = NULL;
8645 rsurface.modelvertex3f_bufferoffset = 0;
8646 rsurface.modelvertex3f_vertexbuffer = 0;
8647 rsurface.modelvertex3f_bufferoffset = 0;
8648 rsurface.modelsvector3f_vertexbuffer = 0;
8649 rsurface.modelsvector3f_bufferoffset = 0;
8650 rsurface.modeltvector3f_vertexbuffer = 0;
8651 rsurface.modeltvector3f_bufferoffset = 0;
8652 rsurface.modelnormal3f_vertexbuffer = 0;
8653 rsurface.modelnormal3f_bufferoffset = 0;
8655 else if (wantnormals)
8657 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8658 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8659 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8660 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8661 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8662 rsurface.modelsvector3f = NULL;
8663 rsurface.modeltvector3f = NULL;
8664 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8665 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8666 rsurface.modelvertexmesh = NULL;
8667 rsurface.modelvertexmesh_vertexbuffer = NULL;
8668 rsurface.modelvertexmesh_bufferoffset = 0;
8669 rsurface.modelvertex3f_vertexbuffer = NULL;
8670 rsurface.modelvertex3f_bufferoffset = 0;
8671 rsurface.modelvertex3f_vertexbuffer = 0;
8672 rsurface.modelvertex3f_bufferoffset = 0;
8673 rsurface.modelsvector3f_vertexbuffer = 0;
8674 rsurface.modelsvector3f_bufferoffset = 0;
8675 rsurface.modeltvector3f_vertexbuffer = 0;
8676 rsurface.modeltvector3f_bufferoffset = 0;
8677 rsurface.modelnormal3f_vertexbuffer = 0;
8678 rsurface.modelnormal3f_bufferoffset = 0;
8682 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8683 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8684 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8685 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8686 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8687 rsurface.modelsvector3f = NULL;
8688 rsurface.modeltvector3f = NULL;
8689 rsurface.modelnormal3f = NULL;
8690 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8691 rsurface.modelvertexmesh = NULL;
8692 rsurface.modelvertexmesh_vertexbuffer = NULL;
8693 rsurface.modelvertexmesh_bufferoffset = 0;
8694 rsurface.modelvertex3f_vertexbuffer = NULL;
8695 rsurface.modelvertex3f_bufferoffset = 0;
8696 rsurface.modelvertex3f_vertexbuffer = 0;
8697 rsurface.modelvertex3f_bufferoffset = 0;
8698 rsurface.modelsvector3f_vertexbuffer = 0;
8699 rsurface.modelsvector3f_bufferoffset = 0;
8700 rsurface.modeltvector3f_vertexbuffer = 0;
8701 rsurface.modeltvector3f_bufferoffset = 0;
8702 rsurface.modelnormal3f_vertexbuffer = 0;
8703 rsurface.modelnormal3f_bufferoffset = 0;
8705 rsurface.modelgeneratedvertex = true;
8709 if (rsurface.entityskeletaltransform3x4)
8711 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8712 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8713 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8714 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8718 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8719 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8720 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8721 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8723 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8724 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8725 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8726 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8727 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8728 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8729 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8730 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8731 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8732 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8733 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8734 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8735 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8736 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8737 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8738 rsurface.modelgeneratedvertex = false;
8740 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8741 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8742 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8743 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8744 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8745 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8746 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8747 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8748 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8749 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8750 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8751 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8752 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8753 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8754 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8755 rsurface.modelelement3i = model->surfmesh.data_element3i;
8756 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8757 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8758 rsurface.modelelement3s = model->surfmesh.data_element3s;
8759 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8760 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8761 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8762 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8763 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8764 rsurface.modelsurfaces = model->data_surfaces;
8765 rsurface.batchgeneratedvertex = false;
8766 rsurface.batchfirstvertex = 0;
8767 rsurface.batchnumvertices = 0;
8768 rsurface.batchfirsttriangle = 0;
8769 rsurface.batchnumtriangles = 0;
8770 rsurface.batchvertex3f = NULL;
8771 rsurface.batchvertex3f_vertexbuffer = NULL;
8772 rsurface.batchvertex3f_bufferoffset = 0;
8773 rsurface.batchsvector3f = NULL;
8774 rsurface.batchsvector3f_vertexbuffer = NULL;
8775 rsurface.batchsvector3f_bufferoffset = 0;
8776 rsurface.batchtvector3f = NULL;
8777 rsurface.batchtvector3f_vertexbuffer = NULL;
8778 rsurface.batchtvector3f_bufferoffset = 0;
8779 rsurface.batchnormal3f = NULL;
8780 rsurface.batchnormal3f_vertexbuffer = NULL;
8781 rsurface.batchnormal3f_bufferoffset = 0;
8782 rsurface.batchlightmapcolor4f = NULL;
8783 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8784 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8785 rsurface.batchtexcoordtexture2f = NULL;
8786 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8787 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8788 rsurface.batchtexcoordlightmap2f = NULL;
8789 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8790 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8791 rsurface.batchskeletalindex4ub = NULL;
8792 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8793 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8794 rsurface.batchskeletalweight4ub = NULL;
8795 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8796 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8797 rsurface.batchvertexmesh = NULL;
8798 rsurface.batchvertexmesh_vertexbuffer = NULL;
8799 rsurface.batchvertexmesh_bufferoffset = 0;
8800 rsurface.batchelement3i = NULL;
8801 rsurface.batchelement3i_indexbuffer = NULL;
8802 rsurface.batchelement3i_bufferoffset = 0;
8803 rsurface.batchelement3s = NULL;
8804 rsurface.batchelement3s_indexbuffer = NULL;
8805 rsurface.batchelement3s_bufferoffset = 0;
8806 rsurface.passcolor4f = NULL;
8807 rsurface.passcolor4f_vertexbuffer = NULL;
8808 rsurface.passcolor4f_bufferoffset = 0;
8809 rsurface.forcecurrenttextureupdate = false;
8812 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)
8814 rsurface.entity = r_refdef.scene.worldentity;
8815 rsurface.skeleton = NULL;
8816 rsurface.ent_skinnum = 0;
8817 rsurface.ent_qwskin = -1;
8818 rsurface.ent_flags = entflags;
8819 rsurface.shadertime = r_refdef.scene.time - shadertime;
8820 rsurface.modelnumvertices = numvertices;
8821 rsurface.modelnumtriangles = numtriangles;
8822 rsurface.matrix = *matrix;
8823 rsurface.inversematrix = *inversematrix;
8824 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8825 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8826 R_EntityMatrix(&rsurface.matrix);
8827 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8828 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8829 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8830 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8831 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8832 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8833 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8834 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8835 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8836 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8837 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8838 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8839 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);
8840 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8841 rsurface.frameblend[0].lerp = 1;
8842 rsurface.ent_alttextures = false;
8843 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8844 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8845 rsurface.entityskeletaltransform3x4 = NULL;
8846 rsurface.entityskeletaltransform3x4buffer = NULL;
8847 rsurface.entityskeletaltransform3x4offset = 0;
8848 rsurface.entityskeletaltransform3x4size = 0;
8849 rsurface.entityskeletalnumtransforms = 0;
8850 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8851 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8852 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8853 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8856 rsurface.modelvertex3f = (float *)vertex3f;
8857 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8858 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8859 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8861 else if (wantnormals)
8863 rsurface.modelvertex3f = (float *)vertex3f;
8864 rsurface.modelsvector3f = NULL;
8865 rsurface.modeltvector3f = NULL;
8866 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8870 rsurface.modelvertex3f = (float *)vertex3f;
8871 rsurface.modelsvector3f = NULL;
8872 rsurface.modeltvector3f = NULL;
8873 rsurface.modelnormal3f = NULL;
8875 rsurface.modelvertexmesh = NULL;
8876 rsurface.modelvertexmesh_vertexbuffer = NULL;
8877 rsurface.modelvertexmesh_bufferoffset = 0;
8878 rsurface.modelvertex3f_vertexbuffer = 0;
8879 rsurface.modelvertex3f_bufferoffset = 0;
8880 rsurface.modelsvector3f_vertexbuffer = 0;
8881 rsurface.modelsvector3f_bufferoffset = 0;
8882 rsurface.modeltvector3f_vertexbuffer = 0;
8883 rsurface.modeltvector3f_bufferoffset = 0;
8884 rsurface.modelnormal3f_vertexbuffer = 0;
8885 rsurface.modelnormal3f_bufferoffset = 0;
8886 rsurface.modelgeneratedvertex = true;
8887 rsurface.modellightmapcolor4f = (float *)color4f;
8888 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8889 rsurface.modellightmapcolor4f_bufferoffset = 0;
8890 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8891 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8892 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8893 rsurface.modeltexcoordlightmap2f = NULL;
8894 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8895 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8896 rsurface.modelskeletalindex4ub = NULL;
8897 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8898 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8899 rsurface.modelskeletalweight4ub = NULL;
8900 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8901 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8902 rsurface.modelelement3i = (int *)element3i;
8903 rsurface.modelelement3i_indexbuffer = NULL;
8904 rsurface.modelelement3i_bufferoffset = 0;
8905 rsurface.modelelement3s = (unsigned short *)element3s;
8906 rsurface.modelelement3s_indexbuffer = NULL;
8907 rsurface.modelelement3s_bufferoffset = 0;
8908 rsurface.modellightmapoffsets = NULL;
8909 rsurface.modelsurfaces = NULL;
8910 rsurface.batchgeneratedvertex = false;
8911 rsurface.batchfirstvertex = 0;
8912 rsurface.batchnumvertices = 0;
8913 rsurface.batchfirsttriangle = 0;
8914 rsurface.batchnumtriangles = 0;
8915 rsurface.batchvertex3f = NULL;
8916 rsurface.batchvertex3f_vertexbuffer = NULL;
8917 rsurface.batchvertex3f_bufferoffset = 0;
8918 rsurface.batchsvector3f = NULL;
8919 rsurface.batchsvector3f_vertexbuffer = NULL;
8920 rsurface.batchsvector3f_bufferoffset = 0;
8921 rsurface.batchtvector3f = NULL;
8922 rsurface.batchtvector3f_vertexbuffer = NULL;
8923 rsurface.batchtvector3f_bufferoffset = 0;
8924 rsurface.batchnormal3f = NULL;
8925 rsurface.batchnormal3f_vertexbuffer = NULL;
8926 rsurface.batchnormal3f_bufferoffset = 0;
8927 rsurface.batchlightmapcolor4f = NULL;
8928 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8929 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8930 rsurface.batchtexcoordtexture2f = NULL;
8931 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8932 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8933 rsurface.batchtexcoordlightmap2f = NULL;
8934 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8935 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8936 rsurface.batchskeletalindex4ub = NULL;
8937 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8938 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8939 rsurface.batchskeletalweight4ub = NULL;
8940 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8941 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8942 rsurface.batchvertexmesh = NULL;
8943 rsurface.batchvertexmesh_vertexbuffer = NULL;
8944 rsurface.batchvertexmesh_bufferoffset = 0;
8945 rsurface.batchelement3i = NULL;
8946 rsurface.batchelement3i_indexbuffer = NULL;
8947 rsurface.batchelement3i_bufferoffset = 0;
8948 rsurface.batchelement3s = NULL;
8949 rsurface.batchelement3s_indexbuffer = NULL;
8950 rsurface.batchelement3s_bufferoffset = 0;
8951 rsurface.passcolor4f = NULL;
8952 rsurface.passcolor4f_vertexbuffer = NULL;
8953 rsurface.passcolor4f_bufferoffset = 0;
8954 rsurface.forcecurrenttextureupdate = true;
8956 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8958 if ((wantnormals || wanttangents) && !normal3f)
8960 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8961 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8963 if (wanttangents && !svector3f)
8965 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8966 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8967 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8972 float RSurf_FogPoint(const float *v)
8974 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8975 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8976 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8977 float FogHeightFade = r_refdef.fogheightfade;
8979 unsigned int fogmasktableindex;
8980 if (r_refdef.fogplaneviewabove)
8981 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8983 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8984 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8985 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8988 float RSurf_FogVertex(const float *v)
8990 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8991 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8992 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8993 float FogHeightFade = rsurface.fogheightfade;
8995 unsigned int fogmasktableindex;
8996 if (r_refdef.fogplaneviewabove)
8997 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8999 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9000 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9001 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9004 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9007 for (i = 0;i < numelements;i++)
9008 outelement3i[i] = inelement3i[i] + adjust;
9011 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9012 extern cvar_t gl_vbo;
9013 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9021 int surfacefirsttriangle;
9022 int surfacenumtriangles;
9023 int surfacefirstvertex;
9024 int surfaceendvertex;
9025 int surfacenumvertices;
9026 int batchnumsurfaces = texturenumsurfaces;
9027 int batchnumvertices;
9028 int batchnumtriangles;
9032 qboolean dynamicvertex;
9036 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9039 q3shaderinfo_deform_t *deform;
9040 const msurface_t *surface, *firstsurface;
9041 r_vertexmesh_t *vertexmesh;
9042 if (!texturenumsurfaces)
9044 // find vertex range of this surface batch
9046 firstsurface = texturesurfacelist[0];
9047 firsttriangle = firstsurface->num_firsttriangle;
9048 batchnumvertices = 0;
9049 batchnumtriangles = 0;
9050 firstvertex = endvertex = firstsurface->num_firstvertex;
9051 for (i = 0;i < texturenumsurfaces;i++)
9053 surface = texturesurfacelist[i];
9054 if (surface != firstsurface + i)
9056 surfacefirstvertex = surface->num_firstvertex;
9057 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9058 surfacenumvertices = surface->num_vertices;
9059 surfacenumtriangles = surface->num_triangles;
9060 if (firstvertex > surfacefirstvertex)
9061 firstvertex = surfacefirstvertex;
9062 if (endvertex < surfaceendvertex)
9063 endvertex = surfaceendvertex;
9064 batchnumvertices += surfacenumvertices;
9065 batchnumtriangles += surfacenumtriangles;
9068 r_refdef.stats[r_stat_batch_batches]++;
9070 r_refdef.stats[r_stat_batch_withgaps]++;
9071 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9072 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9073 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9075 // we now know the vertex range used, and if there are any gaps in it
9076 rsurface.batchfirstvertex = firstvertex;
9077 rsurface.batchnumvertices = endvertex - firstvertex;
9078 rsurface.batchfirsttriangle = firsttriangle;
9079 rsurface.batchnumtriangles = batchnumtriangles;
9081 // this variable holds flags for which properties have been updated that
9082 // may require regenerating vertexmesh array...
9085 // check if any dynamic vertex processing must occur
9086 dynamicvertex = false;
9088 // a cvar to force the dynamic vertex path to be taken, for debugging
9089 if (r_batch_debugdynamicvertexpath.integer)
9093 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9094 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9095 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9096 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9098 dynamicvertex = true;
9101 // if there is a chance of animated vertex colors, it's a dynamic batch
9102 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9106 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9107 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9108 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9109 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9111 dynamicvertex = true;
9112 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9115 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9117 switch (deform->deform)
9120 case Q3DEFORM_PROJECTIONSHADOW:
9121 case Q3DEFORM_TEXT0:
9122 case Q3DEFORM_TEXT1:
9123 case Q3DEFORM_TEXT2:
9124 case Q3DEFORM_TEXT3:
9125 case Q3DEFORM_TEXT4:
9126 case Q3DEFORM_TEXT5:
9127 case Q3DEFORM_TEXT6:
9128 case Q3DEFORM_TEXT7:
9131 case Q3DEFORM_AUTOSPRITE:
9134 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9135 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9136 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9137 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9139 dynamicvertex = true;
9140 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9141 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9143 case Q3DEFORM_AUTOSPRITE2:
9146 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9147 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9148 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9149 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9151 dynamicvertex = true;
9152 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9153 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9155 case Q3DEFORM_NORMAL:
9158 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9159 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9160 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9161 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9163 dynamicvertex = true;
9164 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9165 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9168 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9169 break; // if wavefunc is a nop, ignore this transform
9172 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9173 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9174 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9175 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9177 dynamicvertex = true;
9178 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9179 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9181 case Q3DEFORM_BULGE:
9184 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9185 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9186 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9187 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9189 dynamicvertex = true;
9190 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9191 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9194 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9195 break; // if wavefunc is a nop, ignore this transform
9198 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9199 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9200 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9201 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9203 dynamicvertex = true;
9204 batchneed |= BATCHNEED_ARRAY_VERTEX;
9205 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9209 switch(rsurface.texture->tcgen.tcgen)
9212 case Q3TCGEN_TEXTURE:
9214 case Q3TCGEN_LIGHTMAP:
9217 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9218 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9219 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9220 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9222 dynamicvertex = true;
9223 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9224 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9226 case Q3TCGEN_VECTOR:
9229 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9230 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9231 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9232 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9234 dynamicvertex = true;
9235 batchneed |= BATCHNEED_ARRAY_VERTEX;
9236 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9238 case Q3TCGEN_ENVIRONMENT:
9241 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9242 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9243 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9244 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9246 dynamicvertex = true;
9247 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9248 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9251 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9255 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9256 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9257 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9258 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9260 dynamicvertex = true;
9261 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9262 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9265 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9269 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9270 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9271 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9272 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9274 dynamicvertex = true;
9275 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9278 // when the model data has no vertex buffer (dynamic mesh), we need to
9280 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9281 batchneed |= BATCHNEED_NOGAPS;
9283 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9284 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9285 // we ensure this by treating the vertex batch as dynamic...
9286 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9290 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9291 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9292 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9293 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9295 dynamicvertex = true;
9300 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9301 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9302 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9303 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9304 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9305 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9306 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9307 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9310 // if needsupdate, we have to do a dynamic vertex batch for sure
9311 if (needsupdate & batchneed)
9315 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9316 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9317 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9318 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9320 dynamicvertex = true;
9323 // see if we need to build vertexmesh from arrays
9324 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9328 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9329 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9330 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9331 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9333 dynamicvertex = true;
9336 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9337 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9338 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9340 rsurface.batchvertex3f = rsurface.modelvertex3f;
9341 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9342 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9343 rsurface.batchsvector3f = rsurface.modelsvector3f;
9344 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9345 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9346 rsurface.batchtvector3f = rsurface.modeltvector3f;
9347 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9348 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9349 rsurface.batchnormal3f = rsurface.modelnormal3f;
9350 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9351 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9352 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9353 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9354 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9355 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9356 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9357 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9358 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9359 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9360 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9361 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9362 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9363 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9364 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9365 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9366 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9367 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9368 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9369 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9370 rsurface.batchelement3i = rsurface.modelelement3i;
9371 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9372 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9373 rsurface.batchelement3s = rsurface.modelelement3s;
9374 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9375 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9376 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9377 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9378 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9379 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9380 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9382 // if any dynamic vertex processing has to occur in software, we copy the
9383 // entire surface list together before processing to rebase the vertices
9384 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9386 // if any gaps exist and we do not have a static vertex buffer, we have to
9387 // copy the surface list together to avoid wasting upload bandwidth on the
9388 // vertices in the gaps.
9390 // if gaps exist and we have a static vertex buffer, we can choose whether
9391 // to combine the index buffer ranges into one dynamic index buffer or
9392 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9394 // in many cases the batch is reduced to one draw call.
9396 rsurface.batchmultidraw = false;
9397 rsurface.batchmultidrawnumsurfaces = 0;
9398 rsurface.batchmultidrawsurfacelist = NULL;
9402 // static vertex data, just set pointers...
9403 rsurface.batchgeneratedvertex = false;
9404 // if there are gaps, we want to build a combined index buffer,
9405 // otherwise use the original static buffer with an appropriate offset
9408 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9409 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9410 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9411 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9412 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9414 rsurface.batchmultidraw = true;
9415 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9416 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9419 // build a new triangle elements array for this batch
9420 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9421 rsurface.batchfirsttriangle = 0;
9423 for (i = 0;i < texturenumsurfaces;i++)
9425 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9426 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9427 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9428 numtriangles += surfacenumtriangles;
9430 rsurface.batchelement3i_indexbuffer = NULL;
9431 rsurface.batchelement3i_bufferoffset = 0;
9432 rsurface.batchelement3s = NULL;
9433 rsurface.batchelement3s_indexbuffer = NULL;
9434 rsurface.batchelement3s_bufferoffset = 0;
9435 if (endvertex <= 65536)
9437 // make a 16bit (unsigned short) index array if possible
9438 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9439 for (i = 0;i < numtriangles*3;i++)
9440 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9442 // upload buffer data for the copytriangles batch
9443 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9445 if (rsurface.batchelement3s)
9446 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9447 else if (rsurface.batchelement3i)
9448 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9453 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9454 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9455 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9456 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9461 // something needs software processing, do it for real...
9462 // we only directly handle separate array data in this case and then
9463 // generate interleaved data if needed...
9464 rsurface.batchgeneratedvertex = true;
9465 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9466 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9467 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9468 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9470 // now copy the vertex data into a combined array and make an index array
9471 // (this is what Quake3 does all the time)
9472 // we also apply any skeletal animation here that would have been done in
9473 // the vertex shader, because most of the dynamic vertex animation cases
9474 // need actual vertex positions and normals
9475 //if (dynamicvertex)
9477 rsurface.batchvertexmesh = NULL;
9478 rsurface.batchvertexmesh_vertexbuffer = NULL;
9479 rsurface.batchvertexmesh_bufferoffset = 0;
9480 rsurface.batchvertex3f = NULL;
9481 rsurface.batchvertex3f_vertexbuffer = NULL;
9482 rsurface.batchvertex3f_bufferoffset = 0;
9483 rsurface.batchsvector3f = NULL;
9484 rsurface.batchsvector3f_vertexbuffer = NULL;
9485 rsurface.batchsvector3f_bufferoffset = 0;
9486 rsurface.batchtvector3f = NULL;
9487 rsurface.batchtvector3f_vertexbuffer = NULL;
9488 rsurface.batchtvector3f_bufferoffset = 0;
9489 rsurface.batchnormal3f = NULL;
9490 rsurface.batchnormal3f_vertexbuffer = NULL;
9491 rsurface.batchnormal3f_bufferoffset = 0;
9492 rsurface.batchlightmapcolor4f = NULL;
9493 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9494 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9495 rsurface.batchtexcoordtexture2f = NULL;
9496 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9497 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9498 rsurface.batchtexcoordlightmap2f = NULL;
9499 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9500 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9501 rsurface.batchskeletalindex4ub = NULL;
9502 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9503 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9504 rsurface.batchskeletalweight4ub = NULL;
9505 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9506 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9507 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9508 rsurface.batchelement3i_indexbuffer = NULL;
9509 rsurface.batchelement3i_bufferoffset = 0;
9510 rsurface.batchelement3s = NULL;
9511 rsurface.batchelement3s_indexbuffer = NULL;
9512 rsurface.batchelement3s_bufferoffset = 0;
9513 rsurface.batchskeletaltransform3x4buffer = NULL;
9514 rsurface.batchskeletaltransform3x4offset = 0;
9515 rsurface.batchskeletaltransform3x4size = 0;
9516 // we'll only be setting up certain arrays as needed
9517 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9518 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9519 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9520 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9521 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9522 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9523 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9525 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9526 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9528 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9529 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9530 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9531 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9532 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9533 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9534 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9536 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9537 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9541 for (i = 0;i < texturenumsurfaces;i++)
9543 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9544 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9545 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9546 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9547 // copy only the data requested
9548 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9549 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9550 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9552 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9554 if (rsurface.batchvertex3f)
9555 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9557 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9559 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9561 if (rsurface.modelnormal3f)
9562 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9564 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9566 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9568 if (rsurface.modelsvector3f)
9570 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9571 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9575 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9576 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9579 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9581 if (rsurface.modellightmapcolor4f)
9582 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9584 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9586 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9588 if (rsurface.modeltexcoordtexture2f)
9589 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9591 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9593 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9595 if (rsurface.modeltexcoordlightmap2f)
9596 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9598 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9600 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9602 if (rsurface.modelskeletalindex4ub)
9604 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9605 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9609 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9610 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9611 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9612 for (j = 0;j < surfacenumvertices;j++)
9617 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9618 numvertices += surfacenumvertices;
9619 numtriangles += surfacenumtriangles;
9622 // generate a 16bit index array as well if possible
9623 // (in general, dynamic batches fit)
9624 if (numvertices <= 65536)
9626 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9627 for (i = 0;i < numtriangles*3;i++)
9628 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9631 // since we've copied everything, the batch now starts at 0
9632 rsurface.batchfirstvertex = 0;
9633 rsurface.batchnumvertices = batchnumvertices;
9634 rsurface.batchfirsttriangle = 0;
9635 rsurface.batchnumtriangles = batchnumtriangles;
9638 // apply skeletal animation that would have been done in the vertex shader
9639 if (rsurface.batchskeletaltransform3x4)
9641 const unsigned char *si;
9642 const unsigned char *sw;
9644 const float *b = rsurface.batchskeletaltransform3x4;
9645 float *vp, *vs, *vt, *vn;
9647 float m[3][4], n[3][4];
9648 float tp[3], ts[3], tt[3], tn[3];
9649 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9650 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9651 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9652 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9653 si = rsurface.batchskeletalindex4ub;
9654 sw = rsurface.batchskeletalweight4ub;
9655 vp = rsurface.batchvertex3f;
9656 vs = rsurface.batchsvector3f;
9657 vt = rsurface.batchtvector3f;
9658 vn = rsurface.batchnormal3f;
9659 memset(m[0], 0, sizeof(m));
9660 memset(n[0], 0, sizeof(n));
9661 for (i = 0;i < batchnumvertices;i++)
9663 t[0] = b + si[0]*12;
9666 // common case - only one matrix
9680 else if (sw[2] + sw[3])
9683 t[1] = b + si[1]*12;
9684 t[2] = b + si[2]*12;
9685 t[3] = b + si[3]*12;
9686 w[0] = sw[0] * (1.0f / 255.0f);
9687 w[1] = sw[1] * (1.0f / 255.0f);
9688 w[2] = sw[2] * (1.0f / 255.0f);
9689 w[3] = sw[3] * (1.0f / 255.0f);
9690 // blend the matrices
9691 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9692 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9693 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9694 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9695 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9696 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9697 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9698 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9699 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9700 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9701 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9702 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9707 t[1] = b + si[1]*12;
9708 w[0] = sw[0] * (1.0f / 255.0f);
9709 w[1] = sw[1] * (1.0f / 255.0f);
9710 // blend the matrices
9711 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9712 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9713 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9714 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9715 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9716 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9717 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9718 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9719 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9720 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9721 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9722 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9726 // modify the vertex
9728 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9729 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9730 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9734 // the normal transformation matrix is a set of cross products...
9735 CrossProduct(m[1], m[2], n[0]);
9736 CrossProduct(m[2], m[0], n[1]);
9737 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9739 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9740 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9741 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9742 VectorNormalize(vn);
9747 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9748 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9749 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9750 VectorNormalize(vs);
9753 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9754 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9755 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9756 VectorNormalize(vt);
9761 rsurface.batchskeletaltransform3x4 = NULL;
9762 rsurface.batchskeletalnumtransforms = 0;
9765 // q1bsp surfaces rendered in vertex color mode have to have colors
9766 // calculated based on lightstyles
9767 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9769 // generate color arrays for the surfaces in this list
9774 const unsigned char *lm;
9775 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9776 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9777 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9779 for (i = 0;i < texturenumsurfaces;i++)
9781 surface = texturesurfacelist[i];
9782 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9783 surfacenumvertices = surface->num_vertices;
9784 if (surface->lightmapinfo->samples)
9786 for (j = 0;j < surfacenumvertices;j++)
9788 lm = surface->lightmapinfo->samples + offsets[j];
9789 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9790 VectorScale(lm, scale, c);
9791 if (surface->lightmapinfo->styles[1] != 255)
9793 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9795 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9796 VectorMA(c, scale, lm, c);
9797 if (surface->lightmapinfo->styles[2] != 255)
9800 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9801 VectorMA(c, scale, lm, c);
9802 if (surface->lightmapinfo->styles[3] != 255)
9805 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9806 VectorMA(c, scale, lm, c);
9813 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);
9819 for (j = 0;j < surfacenumvertices;j++)
9821 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9828 // if vertices are deformed (sprite flares and things in maps, possibly
9829 // water waves, bulges and other deformations), modify the copied vertices
9831 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9833 switch (deform->deform)
9836 case Q3DEFORM_PROJECTIONSHADOW:
9837 case Q3DEFORM_TEXT0:
9838 case Q3DEFORM_TEXT1:
9839 case Q3DEFORM_TEXT2:
9840 case Q3DEFORM_TEXT3:
9841 case Q3DEFORM_TEXT4:
9842 case Q3DEFORM_TEXT5:
9843 case Q3DEFORM_TEXT6:
9844 case Q3DEFORM_TEXT7:
9847 case Q3DEFORM_AUTOSPRITE:
9848 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9849 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9850 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9851 VectorNormalize(newforward);
9852 VectorNormalize(newright);
9853 VectorNormalize(newup);
9854 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9855 // rsurface.batchvertex3f_vertexbuffer = NULL;
9856 // rsurface.batchvertex3f_bufferoffset = 0;
9857 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9858 // rsurface.batchsvector3f_vertexbuffer = NULL;
9859 // rsurface.batchsvector3f_bufferoffset = 0;
9860 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9861 // rsurface.batchtvector3f_vertexbuffer = NULL;
9862 // rsurface.batchtvector3f_bufferoffset = 0;
9863 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9864 // rsurface.batchnormal3f_vertexbuffer = NULL;
9865 // rsurface.batchnormal3f_bufferoffset = 0;
9866 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9867 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9868 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9869 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9870 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);
9871 // a single autosprite surface can contain multiple sprites...
9872 for (j = 0;j < batchnumvertices - 3;j += 4)
9874 VectorClear(center);
9875 for (i = 0;i < 4;i++)
9876 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9877 VectorScale(center, 0.25f, center);
9878 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9879 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9880 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9881 for (i = 0;i < 4;i++)
9883 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9884 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9887 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9888 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9889 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);
9891 case Q3DEFORM_AUTOSPRITE2:
9892 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9893 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9894 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9895 VectorNormalize(newforward);
9896 VectorNormalize(newright);
9897 VectorNormalize(newup);
9898 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9899 // rsurface.batchvertex3f_vertexbuffer = NULL;
9900 // rsurface.batchvertex3f_bufferoffset = 0;
9902 const float *v1, *v2;
9912 memset(shortest, 0, sizeof(shortest));
9913 // a single autosprite surface can contain multiple sprites...
9914 for (j = 0;j < batchnumvertices - 3;j += 4)
9916 VectorClear(center);
9917 for (i = 0;i < 4;i++)
9918 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9919 VectorScale(center, 0.25f, center);
9920 // find the two shortest edges, then use them to define the
9921 // axis vectors for rotating around the central axis
9922 for (i = 0;i < 6;i++)
9924 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9925 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9926 l = VectorDistance2(v1, v2);
9927 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9929 l += (1.0f / 1024.0f);
9930 if (shortest[0].length2 > l || i == 0)
9932 shortest[1] = shortest[0];
9933 shortest[0].length2 = l;
9934 shortest[0].v1 = v1;
9935 shortest[0].v2 = v2;
9937 else if (shortest[1].length2 > l || i == 1)
9939 shortest[1].length2 = l;
9940 shortest[1].v1 = v1;
9941 shortest[1].v2 = v2;
9944 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9945 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9946 // this calculates the right vector from the shortest edge
9947 // and the up vector from the edge midpoints
9948 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9949 VectorNormalize(right);
9950 VectorSubtract(end, start, up);
9951 VectorNormalize(up);
9952 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9953 VectorSubtract(rsurface.localvieworigin, center, forward);
9954 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9955 VectorNegate(forward, forward);
9956 VectorReflect(forward, 0, up, forward);
9957 VectorNormalize(forward);
9958 CrossProduct(up, forward, newright);
9959 VectorNormalize(newright);
9960 // rotate the quad around the up axis vector, this is made
9961 // especially easy by the fact we know the quad is flat,
9962 // so we only have to subtract the center position and
9963 // measure distance along the right vector, and then
9964 // multiply that by the newright vector and add back the
9966 // we also need to subtract the old position to undo the
9967 // displacement from the center, which we do with a
9968 // DotProduct, the subtraction/addition of center is also
9969 // optimized into DotProducts here
9970 l = DotProduct(right, center);
9971 for (i = 0;i < 4;i++)
9973 v1 = rsurface.batchvertex3f + 3*(j+i);
9974 f = DotProduct(right, v1) - l;
9975 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9979 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9981 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9982 // rsurface.batchnormal3f_vertexbuffer = NULL;
9983 // rsurface.batchnormal3f_bufferoffset = 0;
9984 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9986 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9988 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9989 // rsurface.batchsvector3f_vertexbuffer = NULL;
9990 // rsurface.batchsvector3f_bufferoffset = 0;
9991 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9992 // rsurface.batchtvector3f_vertexbuffer = NULL;
9993 // rsurface.batchtvector3f_bufferoffset = 0;
9994 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);
9997 case Q3DEFORM_NORMAL:
9998 // deform the normals to make reflections wavey
9999 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10000 rsurface.batchnormal3f_vertexbuffer = NULL;
10001 rsurface.batchnormal3f_bufferoffset = 0;
10002 for (j = 0;j < batchnumvertices;j++)
10005 float *normal = rsurface.batchnormal3f + 3*j;
10006 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10007 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10008 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10009 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10010 VectorNormalize(normal);
10012 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10014 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10015 // rsurface.batchsvector3f_vertexbuffer = NULL;
10016 // rsurface.batchsvector3f_bufferoffset = 0;
10017 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10018 // rsurface.batchtvector3f_vertexbuffer = NULL;
10019 // rsurface.batchtvector3f_bufferoffset = 0;
10020 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);
10023 case Q3DEFORM_WAVE:
10024 // deform vertex array to make wavey water and flags and such
10025 waveparms[0] = deform->waveparms[0];
10026 waveparms[1] = deform->waveparms[1];
10027 waveparms[2] = deform->waveparms[2];
10028 waveparms[3] = deform->waveparms[3];
10029 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10030 break; // if wavefunc is a nop, don't make a dynamic vertex array
10031 // this is how a divisor of vertex influence on deformation
10032 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10033 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10034 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10035 // rsurface.batchvertex3f_vertexbuffer = NULL;
10036 // rsurface.batchvertex3f_bufferoffset = 0;
10037 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10038 // rsurface.batchnormal3f_vertexbuffer = NULL;
10039 // rsurface.batchnormal3f_bufferoffset = 0;
10040 for (j = 0;j < batchnumvertices;j++)
10042 // if the wavefunc depends on time, evaluate it per-vertex
10045 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10046 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10048 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10050 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10051 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10052 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10054 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10055 // rsurface.batchsvector3f_vertexbuffer = NULL;
10056 // rsurface.batchsvector3f_bufferoffset = 0;
10057 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10058 // rsurface.batchtvector3f_vertexbuffer = NULL;
10059 // rsurface.batchtvector3f_bufferoffset = 0;
10060 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);
10063 case Q3DEFORM_BULGE:
10064 // deform vertex array to make the surface have moving bulges
10065 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10066 // rsurface.batchvertex3f_vertexbuffer = NULL;
10067 // rsurface.batchvertex3f_bufferoffset = 0;
10068 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10069 // rsurface.batchnormal3f_vertexbuffer = NULL;
10070 // rsurface.batchnormal3f_bufferoffset = 0;
10071 for (j = 0;j < batchnumvertices;j++)
10073 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10074 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10076 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10077 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10078 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10080 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10081 // rsurface.batchsvector3f_vertexbuffer = NULL;
10082 // rsurface.batchsvector3f_bufferoffset = 0;
10083 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10084 // rsurface.batchtvector3f_vertexbuffer = NULL;
10085 // rsurface.batchtvector3f_bufferoffset = 0;
10086 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);
10089 case Q3DEFORM_MOVE:
10090 // deform vertex array
10091 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10092 break; // if wavefunc is a nop, don't make a dynamic vertex array
10093 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10094 VectorScale(deform->parms, scale, waveparms);
10095 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10096 // rsurface.batchvertex3f_vertexbuffer = NULL;
10097 // rsurface.batchvertex3f_bufferoffset = 0;
10098 for (j = 0;j < batchnumvertices;j++)
10099 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10104 if (rsurface.batchtexcoordtexture2f)
10106 // generate texcoords based on the chosen texcoord source
10107 switch(rsurface.texture->tcgen.tcgen)
10110 case Q3TCGEN_TEXTURE:
10112 case Q3TCGEN_LIGHTMAP:
10113 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10114 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10115 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10116 if (rsurface.batchtexcoordlightmap2f)
10117 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10119 case Q3TCGEN_VECTOR:
10120 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10121 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10122 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10123 for (j = 0;j < batchnumvertices;j++)
10125 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10126 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10129 case Q3TCGEN_ENVIRONMENT:
10130 // make environment reflections using a spheremap
10131 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10132 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10133 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10134 for (j = 0;j < batchnumvertices;j++)
10136 // identical to Q3A's method, but executed in worldspace so
10137 // carried models can be shiny too
10139 float viewer[3], d, reflected[3], worldreflected[3];
10141 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10142 // VectorNormalize(viewer);
10144 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10146 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10147 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10148 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10149 // note: this is proportinal to viewer, so we can normalize later
10151 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10152 VectorNormalize(worldreflected);
10154 // note: this sphere map only uses world x and z!
10155 // so positive and negative y will LOOK THE SAME.
10156 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10157 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10161 // the only tcmod that needs software vertex processing is turbulent, so
10162 // check for it here and apply the changes if needed
10163 // and we only support that as the first one
10164 // (handling a mixture of turbulent and other tcmods would be problematic
10165 // without punting it entirely to a software path)
10166 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10168 amplitude = rsurface.texture->tcmods[0].parms[1];
10169 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10170 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10171 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10172 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10173 for (j = 0;j < batchnumvertices;j++)
10175 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);
10176 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10181 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10183 // convert the modified arrays to vertex structs
10184 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10185 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10186 // rsurface.batchvertexmesh_bufferoffset = 0;
10187 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10188 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10189 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10190 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10191 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10192 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10193 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10195 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10197 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10198 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10201 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10202 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10203 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10204 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10205 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10206 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10207 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10208 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10209 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10210 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10212 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10214 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10215 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10220 // upload buffer data for the dynamic batch
10221 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10223 if (rsurface.batchvertexmesh)
10224 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10227 if (rsurface.batchvertex3f)
10228 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10229 if (rsurface.batchsvector3f)
10230 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10231 if (rsurface.batchtvector3f)
10232 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10233 if (rsurface.batchnormal3f)
10234 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10235 if (rsurface.batchlightmapcolor4f)
10236 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10237 if (rsurface.batchtexcoordtexture2f)
10238 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10239 if (rsurface.batchtexcoordlightmap2f)
10240 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10241 if (rsurface.batchskeletalindex4ub)
10242 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10243 if (rsurface.batchskeletalweight4ub)
10244 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10246 if (rsurface.batchelement3s)
10247 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10248 else if (rsurface.batchelement3i)
10249 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10253 void RSurf_DrawBatch(void)
10255 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10256 // through the pipeline, killing it earlier in the pipeline would have
10257 // per-surface overhead rather than per-batch overhead, so it's best to
10258 // reject it here, before it hits glDraw.
10259 if (rsurface.batchnumtriangles == 0)
10262 // batch debugging code
10263 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10269 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10270 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10273 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10275 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10277 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10278 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);
10285 if (rsurface.batchmultidraw)
10287 // issue multiple draws rather than copying index data
10288 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10289 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10290 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10291 for (i = 0;i < numsurfaces;)
10293 // combine consecutive surfaces as one draw
10294 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10295 if (surfacelist[j] != surfacelist[k] + 1)
10297 firstvertex = surfacelist[i]->num_firstvertex;
10298 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10299 firsttriangle = surfacelist[i]->num_firsttriangle;
10300 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10301 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);
10307 // there is only one consecutive run of index data (may have been combined)
10308 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);
10312 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10314 // pick the closest matching water plane
10315 int planeindex, vertexindex, bestplaneindex = -1;
10319 r_waterstate_waterplane_t *p;
10320 qboolean prepared = false;
10322 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10324 if(p->camera_entity != rsurface.texture->camera_entity)
10329 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10331 if(rsurface.batchnumvertices == 0)
10334 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10336 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10337 d += fabs(PlaneDiff(vert, &p->plane));
10339 if (bestd > d || bestplaneindex < 0)
10342 bestplaneindex = planeindex;
10345 return bestplaneindex;
10346 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10347 // this situation though, as it might be better to render single larger
10348 // batches with useless stuff (backface culled for example) than to
10349 // render multiple smaller batches
10352 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10355 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10356 rsurface.passcolor4f_vertexbuffer = 0;
10357 rsurface.passcolor4f_bufferoffset = 0;
10358 for (i = 0;i < rsurface.batchnumvertices;i++)
10359 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10362 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10369 if (rsurface.passcolor4f)
10371 // generate color arrays
10372 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10373 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10374 rsurface.passcolor4f_vertexbuffer = 0;
10375 rsurface.passcolor4f_bufferoffset = 0;
10376 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)
10378 f = RSurf_FogVertex(v);
10387 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10388 rsurface.passcolor4f_vertexbuffer = 0;
10389 rsurface.passcolor4f_bufferoffset = 0;
10390 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10392 f = RSurf_FogVertex(v);
10401 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10408 if (!rsurface.passcolor4f)
10410 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10411 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10412 rsurface.passcolor4f_vertexbuffer = 0;
10413 rsurface.passcolor4f_bufferoffset = 0;
10414 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)
10416 f = RSurf_FogVertex(v);
10417 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10418 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10419 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10424 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10429 if (!rsurface.passcolor4f)
10431 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10432 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10433 rsurface.passcolor4f_vertexbuffer = 0;
10434 rsurface.passcolor4f_bufferoffset = 0;
10435 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10444 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10449 if (!rsurface.passcolor4f)
10451 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10452 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10453 rsurface.passcolor4f_vertexbuffer = 0;
10454 rsurface.passcolor4f_bufferoffset = 0;
10455 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10457 c2[0] = c[0] + r_refdef.scene.ambient;
10458 c2[1] = c[1] + r_refdef.scene.ambient;
10459 c2[2] = c[2] + r_refdef.scene.ambient;
10464 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10467 rsurface.passcolor4f = NULL;
10468 rsurface.passcolor4f_vertexbuffer = 0;
10469 rsurface.passcolor4f_bufferoffset = 0;
10470 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10471 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10472 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10473 GL_Color(r, g, b, a);
10474 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10475 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10476 R_Mesh_TexMatrix(0, NULL);
10480 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10482 // TODO: optimize applyfog && applycolor case
10483 // just apply fog if necessary, and tint the fog color array if necessary
10484 rsurface.passcolor4f = NULL;
10485 rsurface.passcolor4f_vertexbuffer = 0;
10486 rsurface.passcolor4f_bufferoffset = 0;
10487 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10488 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10489 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10490 GL_Color(r, g, b, a);
10494 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10497 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10498 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10499 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10500 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10501 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10502 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10503 GL_Color(r, g, b, a);
10507 static void RSurf_DrawBatch_GL11_ClampColor(void)
10512 if (!rsurface.passcolor4f)
10514 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10516 c2[0] = bound(0.0f, c1[0], 1.0f);
10517 c2[1] = bound(0.0f, c1[1], 1.0f);
10518 c2[2] = bound(0.0f, c1[2], 1.0f);
10519 c2[3] = bound(0.0f, c1[3], 1.0f);
10523 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10533 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10534 rsurface.passcolor4f_vertexbuffer = 0;
10535 rsurface.passcolor4f_bufferoffset = 0;
10536 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)
10538 f = -DotProduct(r_refdef.view.forward, n);
10540 f = f * 0.85 + 0.15; // work around so stuff won't get black
10541 f *= r_refdef.lightmapintensity;
10542 Vector4Set(c, f, f, f, 1);
10546 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10548 RSurf_DrawBatch_GL11_ApplyFakeLight();
10549 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10550 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10551 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10552 GL_Color(r, g, b, a);
10556 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10564 vec3_t ambientcolor;
10565 vec3_t diffusecolor;
10569 VectorCopy(rsurface.modellight_lightdir, lightdir);
10570 f = 0.5f * r_refdef.lightmapintensity;
10571 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10572 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10573 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10574 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10575 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10576 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10578 if (VectorLength2(diffusecolor) > 0)
10580 // q3-style directional shading
10581 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10582 rsurface.passcolor4f_vertexbuffer = 0;
10583 rsurface.passcolor4f_bufferoffset = 0;
10584 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)
10586 if ((f = DotProduct(n, lightdir)) > 0)
10587 VectorMA(ambientcolor, f, diffusecolor, c);
10589 VectorCopy(ambientcolor, c);
10596 *applycolor = false;
10600 *r = ambientcolor[0];
10601 *g = ambientcolor[1];
10602 *b = ambientcolor[2];
10603 rsurface.passcolor4f = NULL;
10604 rsurface.passcolor4f_vertexbuffer = 0;
10605 rsurface.passcolor4f_bufferoffset = 0;
10609 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10611 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10612 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10613 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10614 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10615 GL_Color(r, g, b, a);
10619 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10627 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10628 rsurface.passcolor4f_vertexbuffer = 0;
10629 rsurface.passcolor4f_bufferoffset = 0;
10631 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10633 f = 1 - RSurf_FogVertex(v);
10641 void RSurf_SetupDepthAndCulling(void)
10643 // submodels are biased to avoid z-fighting with world surfaces that they
10644 // may be exactly overlapping (avoids z-fighting artifacts on certain
10645 // doors and things in Quake maps)
10646 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10647 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10648 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10649 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10652 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10654 // transparent sky would be ridiculous
10655 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10657 R_SetupShader_Generic_NoTexture(false, false);
10658 skyrenderlater = true;
10659 RSurf_SetupDepthAndCulling();
10660 GL_DepthMask(true);
10661 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10662 // skymasking on them, and Quake3 never did sky masking (unlike
10663 // software Quake and software Quake2), so disable the sky masking
10664 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10665 // and skymasking also looks very bad when noclipping outside the
10666 // level, so don't use it then either.
10667 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10669 R_Mesh_ResetTextureState();
10670 if (skyrendermasked)
10672 R_SetupShader_DepthOrShadow(false, false, false);
10673 // depth-only (masking)
10674 GL_ColorMask(0,0,0,0);
10675 // just to make sure that braindead drivers don't draw
10676 // anything despite that colormask...
10677 GL_BlendFunc(GL_ZERO, GL_ONE);
10678 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10679 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10683 R_SetupShader_Generic_NoTexture(false, false);
10685 GL_BlendFunc(GL_ONE, GL_ZERO);
10686 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10687 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10688 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10691 if (skyrendermasked)
10692 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10694 R_Mesh_ResetTextureState();
10695 GL_Color(1, 1, 1, 1);
10698 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10699 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10700 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10702 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10706 // render screenspace normalmap to texture
10707 GL_DepthMask(true);
10708 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10713 // bind lightmap texture
10715 // water/refraction/reflection/camera surfaces have to be handled specially
10716 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10718 int start, end, startplaneindex;
10719 for (start = 0;start < texturenumsurfaces;start = end)
10721 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10722 if(startplaneindex < 0)
10724 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10725 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10729 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10731 // now that we have a batch using the same planeindex, render it
10732 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10734 // render water or distortion background
10735 GL_DepthMask(true);
10736 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);
10738 // blend surface on top
10739 GL_DepthMask(false);
10740 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10743 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10745 // render surface with reflection texture as input
10746 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10747 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);
10754 // render surface batch normally
10755 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10756 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);
10760 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10762 // OpenGL 1.3 path - anything not completely ancient
10763 qboolean applycolor;
10766 const texturelayer_t *layer;
10767 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);
10768 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10770 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10773 int layertexrgbscale;
10774 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10776 if (layerindex == 0)
10777 GL_AlphaTest(true);
10780 GL_AlphaTest(false);
10781 GL_DepthFunc(GL_EQUAL);
10784 GL_DepthMask(layer->depthmask && writedepth);
10785 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10786 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10788 layertexrgbscale = 4;
10789 VectorScale(layer->color, 0.25f, layercolor);
10791 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10793 layertexrgbscale = 2;
10794 VectorScale(layer->color, 0.5f, layercolor);
10798 layertexrgbscale = 1;
10799 VectorScale(layer->color, 1.0f, layercolor);
10801 layercolor[3] = layer->color[3];
10802 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10803 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10804 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10805 switch (layer->type)
10807 case TEXTURELAYERTYPE_LITTEXTURE:
10808 // single-pass lightmapped texture with 2x rgbscale
10809 R_Mesh_TexBind(0, r_texture_white);
10810 R_Mesh_TexMatrix(0, NULL);
10811 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10812 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10813 R_Mesh_TexBind(1, layer->texture);
10814 R_Mesh_TexMatrix(1, &layer->texmatrix);
10815 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10816 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10817 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10818 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10819 else if (FAKELIGHT_ENABLED)
10820 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10821 else if (rsurface.uselightmaptexture)
10822 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10824 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10826 case TEXTURELAYERTYPE_TEXTURE:
10827 // singletexture unlit texture with transparency support
10828 R_Mesh_TexBind(0, layer->texture);
10829 R_Mesh_TexMatrix(0, &layer->texmatrix);
10830 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10831 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10832 R_Mesh_TexBind(1, 0);
10833 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10834 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10836 case TEXTURELAYERTYPE_FOG:
10837 // singletexture fogging
10838 if (layer->texture)
10840 R_Mesh_TexBind(0, layer->texture);
10841 R_Mesh_TexMatrix(0, &layer->texmatrix);
10842 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10843 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10847 R_Mesh_TexBind(0, 0);
10848 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10850 R_Mesh_TexBind(1, 0);
10851 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10852 // generate a color array for the fog pass
10853 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10854 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10858 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10861 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10863 GL_DepthFunc(GL_LEQUAL);
10864 GL_AlphaTest(false);
10868 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10870 // OpenGL 1.1 - crusty old voodoo path
10873 const texturelayer_t *layer;
10874 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);
10875 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10877 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10879 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10881 if (layerindex == 0)
10882 GL_AlphaTest(true);
10885 GL_AlphaTest(false);
10886 GL_DepthFunc(GL_EQUAL);
10889 GL_DepthMask(layer->depthmask && writedepth);
10890 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10891 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10892 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10893 switch (layer->type)
10895 case TEXTURELAYERTYPE_LITTEXTURE:
10896 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10898 // two-pass lit texture with 2x rgbscale
10899 // first the lightmap pass
10900 R_Mesh_TexBind(0, r_texture_white);
10901 R_Mesh_TexMatrix(0, NULL);
10902 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10903 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10904 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10905 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10906 else if (FAKELIGHT_ENABLED)
10907 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10908 else if (rsurface.uselightmaptexture)
10909 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10911 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10912 // then apply the texture to it
10913 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10914 R_Mesh_TexBind(0, layer->texture);
10915 R_Mesh_TexMatrix(0, &layer->texmatrix);
10916 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10917 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10918 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);
10922 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10923 R_Mesh_TexBind(0, layer->texture);
10924 R_Mesh_TexMatrix(0, &layer->texmatrix);
10925 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10926 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10927 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10928 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);
10929 else if (FAKELIGHT_ENABLED)
10930 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);
10932 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);
10935 case TEXTURELAYERTYPE_TEXTURE:
10936 // singletexture unlit texture with transparency support
10937 R_Mesh_TexBind(0, layer->texture);
10938 R_Mesh_TexMatrix(0, &layer->texmatrix);
10939 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10940 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10941 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);
10943 case TEXTURELAYERTYPE_FOG:
10944 // singletexture fogging
10945 if (layer->texture)
10947 R_Mesh_TexBind(0, layer->texture);
10948 R_Mesh_TexMatrix(0, &layer->texmatrix);
10949 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10950 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10954 R_Mesh_TexBind(0, 0);
10955 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10957 // generate a color array for the fog pass
10958 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10959 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10963 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10966 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10968 GL_DepthFunc(GL_LEQUAL);
10969 GL_AlphaTest(false);
10973 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10977 r_vertexgeneric_t *batchvertex;
10980 // R_Mesh_ResetTextureState();
10981 R_SetupShader_Generic_NoTexture(false, false);
10983 if(rsurface.texture && rsurface.texture->currentskinframe)
10985 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10986 c[3] *= rsurface.texture->currentalpha;
10996 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10998 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10999 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11000 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11003 // brighten it up (as texture value 127 means "unlit")
11004 c[0] *= 2 * r_refdef.view.colorscale;
11005 c[1] *= 2 * r_refdef.view.colorscale;
11006 c[2] *= 2 * r_refdef.view.colorscale;
11008 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11009 c[3] *= r_wateralpha.value;
11011 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11013 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11014 GL_DepthMask(false);
11016 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11018 GL_BlendFunc(GL_ONE, GL_ONE);
11019 GL_DepthMask(false);
11021 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11023 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11024 GL_DepthMask(false);
11026 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11028 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11029 GL_DepthMask(false);
11033 GL_BlendFunc(GL_ONE, GL_ZERO);
11034 GL_DepthMask(writedepth);
11037 if (r_showsurfaces.integer == 3)
11039 rsurface.passcolor4f = NULL;
11041 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11043 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11045 rsurface.passcolor4f = NULL;
11046 rsurface.passcolor4f_vertexbuffer = 0;
11047 rsurface.passcolor4f_bufferoffset = 0;
11049 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11051 qboolean applycolor = true;
11054 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11056 r_refdef.lightmapintensity = 1;
11057 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11058 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11060 else if (FAKELIGHT_ENABLED)
11062 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11064 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11065 RSurf_DrawBatch_GL11_ApplyFakeLight();
11066 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11070 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11072 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11073 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11074 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11077 if(!rsurface.passcolor4f)
11078 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11080 RSurf_DrawBatch_GL11_ApplyAmbient();
11081 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11082 if(r_refdef.fogenabled)
11083 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11084 RSurf_DrawBatch_GL11_ClampColor();
11086 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11087 R_SetupShader_Generic_NoTexture(false, false);
11090 else if (!r_refdef.view.showdebug)
11092 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11093 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11094 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11096 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11097 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11099 R_Mesh_PrepareVertices_Generic_Unlock();
11102 else if (r_showsurfaces.integer == 4)
11104 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11105 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11106 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11108 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11109 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11110 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11112 R_Mesh_PrepareVertices_Generic_Unlock();
11115 else if (r_showsurfaces.integer == 2)
11118 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11119 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11120 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11122 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11123 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11124 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11125 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11126 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11127 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11128 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11130 R_Mesh_PrepareVertices_Generic_Unlock();
11131 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11135 int texturesurfaceindex;
11137 const msurface_t *surface;
11138 float surfacecolor4f[4];
11139 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11140 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11142 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11144 surface = texturesurfacelist[texturesurfaceindex];
11145 k = (int)(((size_t)surface) / sizeof(msurface_t));
11146 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11147 for (j = 0;j < surface->num_vertices;j++)
11149 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11150 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11154 R_Mesh_PrepareVertices_Generic_Unlock();
11159 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11162 RSurf_SetupDepthAndCulling();
11163 if (r_showsurfaces.integer)
11165 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11168 switch (vid.renderpath)
11170 case RENDERPATH_GL20:
11171 case RENDERPATH_D3D9:
11172 case RENDERPATH_D3D10:
11173 case RENDERPATH_D3D11:
11174 case RENDERPATH_SOFT:
11175 case RENDERPATH_GLES2:
11176 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11178 case RENDERPATH_GL13:
11179 case RENDERPATH_GLES1:
11180 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11182 case RENDERPATH_GL11:
11183 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11189 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11192 RSurf_SetupDepthAndCulling();
11193 if (r_showsurfaces.integer)
11195 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11198 switch (vid.renderpath)
11200 case RENDERPATH_GL20:
11201 case RENDERPATH_D3D9:
11202 case RENDERPATH_D3D10:
11203 case RENDERPATH_D3D11:
11204 case RENDERPATH_SOFT:
11205 case RENDERPATH_GLES2:
11206 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11208 case RENDERPATH_GL13:
11209 case RENDERPATH_GLES1:
11210 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11212 case RENDERPATH_GL11:
11213 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11219 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11222 int texturenumsurfaces, endsurface;
11223 texture_t *texture;
11224 const msurface_t *surface;
11225 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11227 // if the model is static it doesn't matter what value we give for
11228 // wantnormals and wanttangents, so this logic uses only rules applicable
11229 // to a model, knowing that they are meaningless otherwise
11230 if (ent == r_refdef.scene.worldentity)
11231 RSurf_ActiveWorldEntity();
11232 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11233 RSurf_ActiveModelEntity(ent, false, false, false);
11236 switch (vid.renderpath)
11238 case RENDERPATH_GL20:
11239 case RENDERPATH_D3D9:
11240 case RENDERPATH_D3D10:
11241 case RENDERPATH_D3D11:
11242 case RENDERPATH_SOFT:
11243 case RENDERPATH_GLES2:
11244 RSurf_ActiveModelEntity(ent, true, true, false);
11246 case RENDERPATH_GL11:
11247 case RENDERPATH_GL13:
11248 case RENDERPATH_GLES1:
11249 RSurf_ActiveModelEntity(ent, true, false, false);
11254 if (r_transparentdepthmasking.integer)
11256 qboolean setup = false;
11257 for (i = 0;i < numsurfaces;i = j)
11260 surface = rsurface.modelsurfaces + surfacelist[i];
11261 texture = surface->texture;
11262 rsurface.texture = R_GetCurrentTexture(texture);
11263 rsurface.lightmaptexture = NULL;
11264 rsurface.deluxemaptexture = NULL;
11265 rsurface.uselightmaptexture = false;
11266 // scan ahead until we find a different texture
11267 endsurface = min(i + 1024, numsurfaces);
11268 texturenumsurfaces = 0;
11269 texturesurfacelist[texturenumsurfaces++] = surface;
11270 for (;j < endsurface;j++)
11272 surface = rsurface.modelsurfaces + surfacelist[j];
11273 if (texture != surface->texture)
11275 texturesurfacelist[texturenumsurfaces++] = surface;
11277 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11279 // render the range of surfaces as depth
11283 GL_ColorMask(0,0,0,0);
11285 GL_DepthTest(true);
11286 GL_BlendFunc(GL_ONE, GL_ZERO);
11287 GL_DepthMask(true);
11288 // R_Mesh_ResetTextureState();
11290 RSurf_SetupDepthAndCulling();
11291 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11292 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11293 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11297 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11300 for (i = 0;i < numsurfaces;i = j)
11303 surface = rsurface.modelsurfaces + surfacelist[i];
11304 texture = surface->texture;
11305 rsurface.texture = R_GetCurrentTexture(texture);
11306 // scan ahead until we find a different texture
11307 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11308 texturenumsurfaces = 0;
11309 texturesurfacelist[texturenumsurfaces++] = surface;
11310 if(FAKELIGHT_ENABLED)
11312 rsurface.lightmaptexture = NULL;
11313 rsurface.deluxemaptexture = NULL;
11314 rsurface.uselightmaptexture = false;
11315 for (;j < endsurface;j++)
11317 surface = rsurface.modelsurfaces + surfacelist[j];
11318 if (texture != surface->texture)
11320 texturesurfacelist[texturenumsurfaces++] = surface;
11325 rsurface.lightmaptexture = surface->lightmaptexture;
11326 rsurface.deluxemaptexture = surface->deluxemaptexture;
11327 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11328 for (;j < endsurface;j++)
11330 surface = rsurface.modelsurfaces + surfacelist[j];
11331 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11333 texturesurfacelist[texturenumsurfaces++] = surface;
11336 // render the range of surfaces
11337 if (ent == r_refdef.scene.worldentity)
11338 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11340 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11342 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11345 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11347 // transparent surfaces get pushed off into the transparent queue
11348 int surfacelistindex;
11349 const msurface_t *surface;
11350 vec3_t tempcenter, center;
11351 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11353 surface = texturesurfacelist[surfacelistindex];
11354 if (r_transparent_sortsurfacesbynearest.integer)
11356 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11357 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11358 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11362 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11363 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11364 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11366 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11367 if (rsurface.entity->transparent_offset) // transparent offset
11369 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11370 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11371 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11373 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);
11377 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11379 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11381 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11383 RSurf_SetupDepthAndCulling();
11384 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11385 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11386 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11390 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11394 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11397 if (!rsurface.texture->currentnumlayers)
11399 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11400 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11402 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11404 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11405 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11406 else if (!rsurface.texture->currentnumlayers)
11408 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11410 // in the deferred case, transparent surfaces were queued during prepass
11411 if (!r_shadow_usingdeferredprepass)
11412 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11416 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11417 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11422 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11425 texture_t *texture;
11426 R_FrameData_SetMark();
11427 // break the surface list down into batches by texture and use of lightmapping
11428 for (i = 0;i < numsurfaces;i = j)
11431 // texture is the base texture pointer, rsurface.texture is the
11432 // current frame/skin the texture is directing us to use (for example
11433 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11434 // use skin 1 instead)
11435 texture = surfacelist[i]->texture;
11436 rsurface.texture = R_GetCurrentTexture(texture);
11437 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11439 // if this texture is not the kind we want, skip ahead to the next one
11440 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11444 if(FAKELIGHT_ENABLED || depthonly || prepass)
11446 rsurface.lightmaptexture = NULL;
11447 rsurface.deluxemaptexture = NULL;
11448 rsurface.uselightmaptexture = false;
11449 // simply scan ahead until we find a different texture or lightmap state
11450 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11455 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11456 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11457 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11458 // simply scan ahead until we find a different texture or lightmap state
11459 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11462 // render the range of surfaces
11463 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11465 R_FrameData_ReturnToMark();
11468 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11472 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11475 if (!rsurface.texture->currentnumlayers)
11477 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11478 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11480 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11482 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11483 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11484 else if (!rsurface.texture->currentnumlayers)
11486 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11488 // in the deferred case, transparent surfaces were queued during prepass
11489 if (!r_shadow_usingdeferredprepass)
11490 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11494 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11495 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11500 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11503 texture_t *texture;
11504 R_FrameData_SetMark();
11505 // break the surface list down into batches by texture and use of lightmapping
11506 for (i = 0;i < numsurfaces;i = j)
11509 // texture is the base texture pointer, rsurface.texture is the
11510 // current frame/skin the texture is directing us to use (for example
11511 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11512 // use skin 1 instead)
11513 texture = surfacelist[i]->texture;
11514 rsurface.texture = R_GetCurrentTexture(texture);
11515 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11517 // if this texture is not the kind we want, skip ahead to the next one
11518 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11522 if(FAKELIGHT_ENABLED || depthonly || prepass)
11524 rsurface.lightmaptexture = NULL;
11525 rsurface.deluxemaptexture = NULL;
11526 rsurface.uselightmaptexture = false;
11527 // simply scan ahead until we find a different texture or lightmap state
11528 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11533 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11534 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11535 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11536 // simply scan ahead until we find a different texture or lightmap state
11537 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11540 // render the range of surfaces
11541 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11543 R_FrameData_ReturnToMark();
11546 float locboxvertex3f[6*4*3] =
11548 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11549 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11550 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11551 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11552 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11553 1,0,0, 0,0,0, 0,1,0, 1,1,0
11556 unsigned short locboxelements[6*2*3] =
11561 12,13,14, 12,14,15,
11562 16,17,18, 16,18,19,
11566 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11569 cl_locnode_t *loc = (cl_locnode_t *)ent;
11571 float vertex3f[6*4*3];
11573 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11574 GL_DepthMask(false);
11575 GL_DepthRange(0, 1);
11576 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11577 GL_DepthTest(true);
11578 GL_CullFace(GL_NONE);
11579 R_EntityMatrix(&identitymatrix);
11581 // R_Mesh_ResetTextureState();
11583 i = surfacelist[0];
11584 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11585 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11586 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11587 surfacelist[0] < 0 ? 0.5f : 0.125f);
11589 if (VectorCompare(loc->mins, loc->maxs))
11591 VectorSet(size, 2, 2, 2);
11592 VectorMA(loc->mins, -0.5f, size, mins);
11596 VectorCopy(loc->mins, mins);
11597 VectorSubtract(loc->maxs, loc->mins, size);
11600 for (i = 0;i < 6*4*3;)
11601 for (j = 0;j < 3;j++, i++)
11602 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11604 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11605 R_SetupShader_Generic_NoTexture(false, false);
11606 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11609 void R_DrawLocs(void)
11612 cl_locnode_t *loc, *nearestloc;
11614 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11615 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11617 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11618 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11622 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11624 if (decalsystem->decals)
11625 Mem_Free(decalsystem->decals);
11626 memset(decalsystem, 0, sizeof(*decalsystem));
11629 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
11632 tridecal_t *decals;
11635 // expand or initialize the system
11636 if (decalsystem->maxdecals <= decalsystem->numdecals)
11638 decalsystem_t old = *decalsystem;
11639 qboolean useshortelements;
11640 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11641 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11642 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)));
11643 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11644 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11645 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11646 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11647 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11648 if (decalsystem->numdecals)
11649 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11651 Mem_Free(old.decals);
11652 for (i = 0;i < decalsystem->maxdecals*3;i++)
11653 decalsystem->element3i[i] = i;
11654 if (useshortelements)
11655 for (i = 0;i < decalsystem->maxdecals*3;i++)
11656 decalsystem->element3s[i] = i;
11659 // grab a decal and search for another free slot for the next one
11660 decals = decalsystem->decals;
11661 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11662 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11664 decalsystem->freedecal = i;
11665 if (decalsystem->numdecals <= i)
11666 decalsystem->numdecals = i + 1;
11668 // initialize the decal
11670 decal->triangleindex = triangleindex;
11671 decal->surfaceindex = surfaceindex;
11672 decal->decalsequence = decalsequence;
11673 decal->color4f[0][0] = c0[0];
11674 decal->color4f[0][1] = c0[1];
11675 decal->color4f[0][2] = c0[2];
11676 decal->color4f[0][3] = 1;
11677 decal->color4f[1][0] = c1[0];
11678 decal->color4f[1][1] = c1[1];
11679 decal->color4f[1][2] = c1[2];
11680 decal->color4f[1][3] = 1;
11681 decal->color4f[2][0] = c2[0];
11682 decal->color4f[2][1] = c2[1];
11683 decal->color4f[2][2] = c2[2];
11684 decal->color4f[2][3] = 1;
11685 decal->vertex3f[0][0] = v0[0];
11686 decal->vertex3f[0][1] = v0[1];
11687 decal->vertex3f[0][2] = v0[2];
11688 decal->vertex3f[1][0] = v1[0];
11689 decal->vertex3f[1][1] = v1[1];
11690 decal->vertex3f[1][2] = v1[2];
11691 decal->vertex3f[2][0] = v2[0];
11692 decal->vertex3f[2][1] = v2[1];
11693 decal->vertex3f[2][2] = v2[2];
11694 decal->texcoord2f[0][0] = t0[0];
11695 decal->texcoord2f[0][1] = t0[1];
11696 decal->texcoord2f[1][0] = t1[0];
11697 decal->texcoord2f[1][1] = t1[1];
11698 decal->texcoord2f[2][0] = t2[0];
11699 decal->texcoord2f[2][1] = t2[1];
11700 TriangleNormal(v0, v1, v2, decal->plane);
11701 VectorNormalize(decal->plane);
11702 decal->plane[3] = DotProduct(v0, decal->plane);
11705 extern cvar_t cl_decals_bias;
11706 extern cvar_t cl_decals_models;
11707 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11708 // baseparms, parms, temps
11709 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11714 const float *vertex3f;
11715 const float *normal3f;
11717 float points[2][9][3];
11724 e = rsurface.modelelement3i + 3*triangleindex;
11726 vertex3f = rsurface.modelvertex3f;
11727 normal3f = rsurface.modelnormal3f;
11731 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11733 index = 3*e[cornerindex];
11734 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11739 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11741 index = 3*e[cornerindex];
11742 VectorCopy(vertex3f + index, v[cornerindex]);
11747 //TriangleNormal(v[0], v[1], v[2], normal);
11748 //if (DotProduct(normal, localnormal) < 0.0f)
11750 // clip by each of the box planes formed from the projection matrix
11751 // if anything survives, we emit the decal
11752 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]);
11755 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]);
11758 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]);
11761 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]);
11764 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]);
11767 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]);
11770 // some part of the triangle survived, so we have to accept it...
11773 // dynamic always uses the original triangle
11775 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11777 index = 3*e[cornerindex];
11778 VectorCopy(vertex3f + index, v[cornerindex]);
11781 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11783 // convert vertex positions to texcoords
11784 Matrix4x4_Transform(projection, v[cornerindex], temp);
11785 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11786 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11787 // calculate distance fade from the projection origin
11788 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11789 f = bound(0.0f, f, 1.0f);
11790 c[cornerindex][0] = r * f;
11791 c[cornerindex][1] = g * f;
11792 c[cornerindex][2] = b * f;
11793 c[cornerindex][3] = 1.0f;
11794 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11797 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);
11799 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11800 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);
11802 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
11804 matrix4x4_t projection;
11805 decalsystem_t *decalsystem;
11808 const msurface_t *surface;
11809 const msurface_t *surfaces;
11810 const int *surfacelist;
11811 const texture_t *texture;
11813 int numsurfacelist;
11814 int surfacelistindex;
11817 float localorigin[3];
11818 float localnormal[3];
11819 float localmins[3];
11820 float localmaxs[3];
11823 float planes[6][4];
11826 int bih_triangles_count;
11827 int bih_triangles[256];
11828 int bih_surfaces[256];
11830 decalsystem = &ent->decalsystem;
11831 model = ent->model;
11832 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11834 R_DecalSystem_Reset(&ent->decalsystem);
11838 if (!model->brush.data_leafs && !cl_decals_models.integer)
11840 if (decalsystem->model)
11841 R_DecalSystem_Reset(decalsystem);
11845 if (decalsystem->model != model)
11846 R_DecalSystem_Reset(decalsystem);
11847 decalsystem->model = model;
11849 RSurf_ActiveModelEntity(ent, true, false, false);
11851 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11852 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11853 VectorNormalize(localnormal);
11854 localsize = worldsize*rsurface.inversematrixscale;
11855 localmins[0] = localorigin[0] - localsize;
11856 localmins[1] = localorigin[1] - localsize;
11857 localmins[2] = localorigin[2] - localsize;
11858 localmaxs[0] = localorigin[0] + localsize;
11859 localmaxs[1] = localorigin[1] + localsize;
11860 localmaxs[2] = localorigin[2] + localsize;
11862 //VectorCopy(localnormal, planes[4]);
11863 //VectorVectors(planes[4], planes[2], planes[0]);
11864 AnglesFromVectors(angles, localnormal, NULL, false);
11865 AngleVectors(angles, planes[0], planes[2], planes[4]);
11866 VectorNegate(planes[0], planes[1]);
11867 VectorNegate(planes[2], planes[3]);
11868 VectorNegate(planes[4], planes[5]);
11869 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11870 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11871 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11872 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11873 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11874 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11879 matrix4x4_t forwardprojection;
11880 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11881 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11886 float projectionvector[4][3];
11887 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11888 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11889 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11890 projectionvector[0][0] = planes[0][0] * ilocalsize;
11891 projectionvector[0][1] = planes[1][0] * ilocalsize;
11892 projectionvector[0][2] = planes[2][0] * ilocalsize;
11893 projectionvector[1][0] = planes[0][1] * ilocalsize;
11894 projectionvector[1][1] = planes[1][1] * ilocalsize;
11895 projectionvector[1][2] = planes[2][1] * ilocalsize;
11896 projectionvector[2][0] = planes[0][2] * ilocalsize;
11897 projectionvector[2][1] = planes[1][2] * ilocalsize;
11898 projectionvector[2][2] = planes[2][2] * ilocalsize;
11899 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11900 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11901 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11902 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11906 dynamic = model->surfmesh.isanimated;
11907 numsurfacelist = model->nummodelsurfaces;
11908 surfacelist = model->sortedmodelsurfaces;
11909 surfaces = model->data_surfaces;
11912 bih_triangles_count = -1;
11915 if(model->render_bih.numleafs)
11916 bih = &model->render_bih;
11917 else if(model->collision_bih.numleafs)
11918 bih = &model->collision_bih;
11921 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11922 if(bih_triangles_count == 0)
11924 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11926 if(bih_triangles_count > 0)
11928 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11930 surfaceindex = bih_surfaces[triangleindex];
11931 surface = surfaces + surfaceindex;
11932 texture = surface->texture;
11933 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11935 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11937 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11942 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11944 surfaceindex = surfacelist[surfacelistindex];
11945 surface = surfaces + surfaceindex;
11946 // check cull box first because it rejects more than any other check
11947 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11949 // skip transparent surfaces
11950 texture = surface->texture;
11951 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11953 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11955 numtriangles = surface->num_triangles;
11956 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11957 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11962 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11963 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
11965 int renderentityindex;
11966 float worldmins[3];
11967 float worldmaxs[3];
11968 entity_render_t *ent;
11970 if (!cl_decals_newsystem.integer)
11973 worldmins[0] = worldorigin[0] - worldsize;
11974 worldmins[1] = worldorigin[1] - worldsize;
11975 worldmins[2] = worldorigin[2] - worldsize;
11976 worldmaxs[0] = worldorigin[0] + worldsize;
11977 worldmaxs[1] = worldorigin[1] + worldsize;
11978 worldmaxs[2] = worldorigin[2] + worldsize;
11980 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11982 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11984 ent = r_refdef.scene.entities[renderentityindex];
11985 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11988 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11992 typedef struct r_decalsystem_splatqueue_s
11994 vec3_t worldorigin;
11995 vec3_t worldnormal;
12001 r_decalsystem_splatqueue_t;
12003 int r_decalsystem_numqueued = 0;
12004 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12006 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)
12008 r_decalsystem_splatqueue_t *queue;
12010 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12013 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12014 VectorCopy(worldorigin, queue->worldorigin);
12015 VectorCopy(worldnormal, queue->worldnormal);
12016 Vector4Set(queue->color, r, g, b, a);
12017 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12018 queue->worldsize = worldsize;
12019 queue->decalsequence = cl.decalsequence++;
12022 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12025 r_decalsystem_splatqueue_t *queue;
12027 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12028 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);
12029 r_decalsystem_numqueued = 0;
12032 extern cvar_t cl_decals_max;
12033 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12036 decalsystem_t *decalsystem = &ent->decalsystem;
12043 if (!decalsystem->numdecals)
12046 if (r_showsurfaces.integer)
12049 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12051 R_DecalSystem_Reset(decalsystem);
12055 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12056 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12058 if (decalsystem->lastupdatetime)
12059 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12062 decalsystem->lastupdatetime = r_refdef.scene.time;
12063 numdecals = decalsystem->numdecals;
12065 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12067 if (decal->color4f[0][3])
12069 decal->lived += frametime;
12070 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12072 memset(decal, 0, sizeof(*decal));
12073 if (decalsystem->freedecal > i)
12074 decalsystem->freedecal = i;
12078 decal = decalsystem->decals;
12079 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12082 // collapse the array by shuffling the tail decals into the gaps
12085 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12086 decalsystem->freedecal++;
12087 if (decalsystem->freedecal == numdecals)
12089 decal[decalsystem->freedecal] = decal[--numdecals];
12092 decalsystem->numdecals = numdecals;
12094 if (numdecals <= 0)
12096 // if there are no decals left, reset decalsystem
12097 R_DecalSystem_Reset(decalsystem);
12101 extern skinframe_t *decalskinframe;
12102 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12105 decalsystem_t *decalsystem = &ent->decalsystem;
12114 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12117 numdecals = decalsystem->numdecals;
12121 if (r_showsurfaces.integer)
12124 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12126 R_DecalSystem_Reset(decalsystem);
12130 // if the model is static it doesn't matter what value we give for
12131 // wantnormals and wanttangents, so this logic uses only rules applicable
12132 // to a model, knowing that they are meaningless otherwise
12133 if (ent == r_refdef.scene.worldentity)
12134 RSurf_ActiveWorldEntity();
12136 RSurf_ActiveModelEntity(ent, false, false, false);
12138 decalsystem->lastupdatetime = r_refdef.scene.time;
12140 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12142 // update vertex positions for animated models
12143 v3f = decalsystem->vertex3f;
12144 c4f = decalsystem->color4f;
12145 t2f = decalsystem->texcoord2f;
12146 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12148 if (!decal->color4f[0][3])
12151 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12155 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12158 // update color values for fading decals
12159 if (decal->lived >= cl_decals_time.value)
12160 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12164 c4f[ 0] = decal->color4f[0][0] * alpha;
12165 c4f[ 1] = decal->color4f[0][1] * alpha;
12166 c4f[ 2] = decal->color4f[0][2] * alpha;
12168 c4f[ 4] = decal->color4f[1][0] * alpha;
12169 c4f[ 5] = decal->color4f[1][1] * alpha;
12170 c4f[ 6] = decal->color4f[1][2] * alpha;
12172 c4f[ 8] = decal->color4f[2][0] * alpha;
12173 c4f[ 9] = decal->color4f[2][1] * alpha;
12174 c4f[10] = decal->color4f[2][2] * alpha;
12177 t2f[0] = decal->texcoord2f[0][0];
12178 t2f[1] = decal->texcoord2f[0][1];
12179 t2f[2] = decal->texcoord2f[1][0];
12180 t2f[3] = decal->texcoord2f[1][1];
12181 t2f[4] = decal->texcoord2f[2][0];
12182 t2f[5] = decal->texcoord2f[2][1];
12184 // update vertex positions for animated models
12185 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12187 e = rsurface.modelelement3i + 3*decal->triangleindex;
12188 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12189 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12190 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12194 VectorCopy(decal->vertex3f[0], v3f);
12195 VectorCopy(decal->vertex3f[1], v3f + 3);
12196 VectorCopy(decal->vertex3f[2], v3f + 6);
12199 if (r_refdef.fogenabled)
12201 alpha = RSurf_FogVertex(v3f);
12202 VectorScale(c4f, alpha, c4f);
12203 alpha = RSurf_FogVertex(v3f + 3);
12204 VectorScale(c4f + 4, alpha, c4f + 4);
12205 alpha = RSurf_FogVertex(v3f + 6);
12206 VectorScale(c4f + 8, alpha, c4f + 8);
12217 r_refdef.stats[r_stat_drawndecals] += numtris;
12219 // now render the decals all at once
12220 // (this assumes they all use one particle font texture!)
12221 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);
12222 // R_Mesh_ResetTextureState();
12223 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12224 GL_DepthMask(false);
12225 GL_DepthRange(0, 1);
12226 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12227 GL_DepthTest(true);
12228 GL_CullFace(GL_NONE);
12229 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12230 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12231 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12235 static void R_DrawModelDecals(void)
12239 // fade faster when there are too many decals
12240 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12241 for (i = 0;i < r_refdef.scene.numentities;i++)
12242 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12244 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12245 for (i = 0;i < r_refdef.scene.numentities;i++)
12246 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12247 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12249 R_DecalSystem_ApplySplatEntitiesQueue();
12251 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12252 for (i = 0;i < r_refdef.scene.numentities;i++)
12253 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12255 r_refdef.stats[r_stat_totaldecals] += numdecals;
12257 if (r_showsurfaces.integer)
12260 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12262 for (i = 0;i < r_refdef.scene.numentities;i++)
12264 if (!r_refdef.viewcache.entityvisible[i])
12266 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12267 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12271 extern cvar_t mod_collision_bih;
12272 static void R_DrawDebugModel(void)
12274 entity_render_t *ent = rsurface.entity;
12275 int i, j, flagsmask;
12276 const msurface_t *surface;
12277 dp_model_t *model = ent->model;
12279 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12282 if (r_showoverdraw.value > 0)
12284 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12285 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12286 R_SetupShader_Generic_NoTexture(false, false);
12287 GL_DepthTest(false);
12288 GL_DepthMask(false);
12289 GL_DepthRange(0, 1);
12290 GL_BlendFunc(GL_ONE, GL_ONE);
12291 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12293 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12295 rsurface.texture = R_GetCurrentTexture(surface->texture);
12296 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12298 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12299 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12300 if (!rsurface.texture->currentlayers->depthmask)
12301 GL_Color(c, 0, 0, 1.0f);
12302 else if (ent == r_refdef.scene.worldentity)
12303 GL_Color(c, c, c, 1.0f);
12305 GL_Color(0, c, 0, 1.0f);
12306 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12310 rsurface.texture = NULL;
12313 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12315 // R_Mesh_ResetTextureState();
12316 R_SetupShader_Generic_NoTexture(false, false);
12317 GL_DepthRange(0, 1);
12318 GL_DepthTest(!r_showdisabledepthtest.integer);
12319 GL_DepthMask(false);
12320 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12322 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12326 qboolean cullbox = false;
12327 const q3mbrush_t *brush;
12328 const bih_t *bih = &model->collision_bih;
12329 const bih_leaf_t *bihleaf;
12330 float vertex3f[3][3];
12331 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12332 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12334 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12336 switch (bihleaf->type)
12339 brush = model->brush.data_brushes + bihleaf->itemindex;
12340 if (brush->colbrushf && brush->colbrushf->numtriangles)
12342 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);
12343 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12344 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12347 case BIH_COLLISIONTRIANGLE:
12348 triangleindex = bihleaf->itemindex;
12349 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12350 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12351 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12352 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);
12353 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12354 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12356 case BIH_RENDERTRIANGLE:
12357 triangleindex = bihleaf->itemindex;
12358 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12359 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12360 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12361 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);
12362 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12363 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12369 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12372 if (r_showtris.integer && qglPolygonMode)
12374 if (r_showdisabledepthtest.integer)
12376 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12377 GL_DepthMask(false);
12381 GL_BlendFunc(GL_ONE, GL_ZERO);
12382 GL_DepthMask(true);
12384 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12385 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12387 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12389 rsurface.texture = R_GetCurrentTexture(surface->texture);
12390 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12392 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12393 if (!rsurface.texture->currentlayers->depthmask)
12394 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12395 else if (ent == r_refdef.scene.worldentity)
12396 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12398 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12399 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12403 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12404 rsurface.texture = NULL;
12407 if (r_shownormals.value != 0 && qglBegin)
12411 if (r_showdisabledepthtest.integer)
12413 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12414 GL_DepthMask(false);
12418 GL_BlendFunc(GL_ONE, GL_ZERO);
12419 GL_DepthMask(true);
12421 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12423 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12425 rsurface.texture = R_GetCurrentTexture(surface->texture);
12426 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12428 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12429 qglBegin(GL_LINES);
12430 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12432 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12434 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12435 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12436 qglVertex3f(v[0], v[1], v[2]);
12437 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12438 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12439 qglVertex3f(v[0], v[1], v[2]);
12442 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12444 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12446 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12447 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12448 qglVertex3f(v[0], v[1], v[2]);
12449 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12450 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12451 qglVertex3f(v[0], v[1], v[2]);
12454 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12456 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12458 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12459 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12460 qglVertex3f(v[0], v[1], v[2]);
12461 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12462 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12463 qglVertex3f(v[0], v[1], v[2]);
12466 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12468 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12470 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12471 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12472 qglVertex3f(v[0], v[1], v[2]);
12473 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12474 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12475 qglVertex3f(v[0], v[1], v[2]);
12482 rsurface.texture = NULL;
12487 int r_maxsurfacelist = 0;
12488 const msurface_t **r_surfacelist = NULL;
12489 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12491 int i, j, endj, flagsmask;
12492 dp_model_t *model = r_refdef.scene.worldmodel;
12493 msurface_t *surfaces;
12494 unsigned char *update;
12495 int numsurfacelist = 0;
12499 if (r_maxsurfacelist < model->num_surfaces)
12501 r_maxsurfacelist = model->num_surfaces;
12503 Mem_Free((msurface_t**)r_surfacelist);
12504 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12507 RSurf_ActiveWorldEntity();
12509 surfaces = model->data_surfaces;
12510 update = model->brushq1.lightmapupdateflags;
12512 // update light styles on this submodel
12513 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12515 model_brush_lightstyleinfo_t *style;
12516 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12518 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12520 int *list = style->surfacelist;
12521 style->value = r_refdef.scene.lightstylevalue[style->style];
12522 for (j = 0;j < style->numsurfaces;j++)
12523 update[list[j]] = true;
12528 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12532 R_DrawDebugModel();
12533 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12537 rsurface.lightmaptexture = NULL;
12538 rsurface.deluxemaptexture = NULL;
12539 rsurface.uselightmaptexture = false;
12540 rsurface.texture = NULL;
12541 rsurface.rtlight = NULL;
12542 numsurfacelist = 0;
12543 // add visible surfaces to draw list
12544 for (i = 0;i < model->nummodelsurfaces;i++)
12546 j = model->sortedmodelsurfaces[i];
12547 if (r_refdef.viewcache.world_surfacevisible[j])
12548 r_surfacelist[numsurfacelist++] = surfaces + j;
12550 // update lightmaps if needed
12551 if (model->brushq1.firstrender)
12553 model->brushq1.firstrender = false;
12554 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12556 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12560 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12561 if (r_refdef.viewcache.world_surfacevisible[j])
12563 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12565 // don't do anything if there were no surfaces
12566 if (!numsurfacelist)
12568 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12571 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12573 // add to stats if desired
12574 if (r_speeds.integer && !skysurfaces && !depthonly)
12576 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12577 for (j = 0;j < numsurfacelist;j++)
12578 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12581 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12584 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12586 int i, j, endj, flagsmask;
12587 dp_model_t *model = ent->model;
12588 msurface_t *surfaces;
12589 unsigned char *update;
12590 int numsurfacelist = 0;
12594 if (r_maxsurfacelist < model->num_surfaces)
12596 r_maxsurfacelist = model->num_surfaces;
12598 Mem_Free((msurface_t **)r_surfacelist);
12599 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12602 // if the model is static it doesn't matter what value we give for
12603 // wantnormals and wanttangents, so this logic uses only rules applicable
12604 // to a model, knowing that they are meaningless otherwise
12605 if (ent == r_refdef.scene.worldentity)
12606 RSurf_ActiveWorldEntity();
12607 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12608 RSurf_ActiveModelEntity(ent, false, false, false);
12610 RSurf_ActiveModelEntity(ent, true, true, true);
12611 else if (depthonly)
12613 switch (vid.renderpath)
12615 case RENDERPATH_GL20:
12616 case RENDERPATH_D3D9:
12617 case RENDERPATH_D3D10:
12618 case RENDERPATH_D3D11:
12619 case RENDERPATH_SOFT:
12620 case RENDERPATH_GLES2:
12621 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12623 case RENDERPATH_GL11:
12624 case RENDERPATH_GL13:
12625 case RENDERPATH_GLES1:
12626 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12632 switch (vid.renderpath)
12634 case RENDERPATH_GL20:
12635 case RENDERPATH_D3D9:
12636 case RENDERPATH_D3D10:
12637 case RENDERPATH_D3D11:
12638 case RENDERPATH_SOFT:
12639 case RENDERPATH_GLES2:
12640 RSurf_ActiveModelEntity(ent, true, true, false);
12642 case RENDERPATH_GL11:
12643 case RENDERPATH_GL13:
12644 case RENDERPATH_GLES1:
12645 RSurf_ActiveModelEntity(ent, true, false, false);
12650 surfaces = model->data_surfaces;
12651 update = model->brushq1.lightmapupdateflags;
12653 // update light styles
12654 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12656 model_brush_lightstyleinfo_t *style;
12657 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12659 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12661 int *list = style->surfacelist;
12662 style->value = r_refdef.scene.lightstylevalue[style->style];
12663 for (j = 0;j < style->numsurfaces;j++)
12664 update[list[j]] = true;
12669 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12673 R_DrawDebugModel();
12674 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12678 rsurface.lightmaptexture = NULL;
12679 rsurface.deluxemaptexture = NULL;
12680 rsurface.uselightmaptexture = false;
12681 rsurface.texture = NULL;
12682 rsurface.rtlight = NULL;
12683 numsurfacelist = 0;
12684 // add visible surfaces to draw list
12685 for (i = 0;i < model->nummodelsurfaces;i++)
12686 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12687 // don't do anything if there were no surfaces
12688 if (!numsurfacelist)
12690 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12693 // update lightmaps if needed
12697 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12702 R_BuildLightMap(ent, surfaces + j);
12707 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12709 // add to stats if desired
12710 if (r_speeds.integer && !skysurfaces && !depthonly)
12712 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12713 for (j = 0;j < numsurfacelist;j++)
12714 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12717 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12720 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12722 static texture_t texture;
12723 static msurface_t surface;
12724 const msurface_t *surfacelist = &surface;
12726 // fake enough texture and surface state to render this geometry
12728 texture.update_lastrenderframe = -1; // regenerate this texture
12729 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12730 texture.basealpha = 1.0f;
12731 texture.currentskinframe = skinframe;
12732 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12733 texture.offsetmapping = OFFSETMAPPING_OFF;
12734 texture.offsetscale = 1;
12735 texture.specularscalemod = 1;
12736 texture.specularpowermod = 1;
12737 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12738 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12739 // JUST GREP FOR "specularscalemod = 1".
12741 surface.texture = &texture;
12742 surface.num_triangles = numtriangles;
12743 surface.num_firsttriangle = firsttriangle;
12744 surface.num_vertices = numvertices;
12745 surface.num_firstvertex = firstvertex;
12748 rsurface.texture = R_GetCurrentTexture(surface.texture);
12749 rsurface.lightmaptexture = NULL;
12750 rsurface.deluxemaptexture = NULL;
12751 rsurface.uselightmaptexture = false;
12752 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12755 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)
12757 static msurface_t surface;
12758 const msurface_t *surfacelist = &surface;
12760 // fake enough texture and surface state to render this geometry
12761 surface.texture = texture;
12762 surface.num_triangles = numtriangles;
12763 surface.num_firsttriangle = firsttriangle;
12764 surface.num_vertices = numvertices;
12765 surface.num_firstvertex = firstvertex;
12768 rsurface.texture = R_GetCurrentTexture(surface.texture);
12769 rsurface.lightmaptexture = NULL;
12770 rsurface.deluxemaptexture = NULL;
12771 rsurface.uselightmaptexture = false;
12772 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);