2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47 static qboolean r_gpuskeletal;
54 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
55 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
61 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
62 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
63 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
64 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
65 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
73 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
81 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
82 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
85 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
92 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
93 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
102 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
127 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
138 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
149 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
150 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
156 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
157 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
158 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
162 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
163 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
172 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
175 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
178 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
179 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
180 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
181 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
182 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
183 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
184 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
186 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
187 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
188 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
189 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
190 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
191 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
192 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
193 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
194 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
196 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
197 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
198 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
199 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
201 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
202 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
204 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
205 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
206 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
207 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
208 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
209 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
211 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
212 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
213 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
214 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
215 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
218 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
219 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
220 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
222 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
224 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
226 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
228 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
230 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
231 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
232 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
235 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
236 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
238 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
240 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
241 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
243 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
244 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
245 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
246 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
249 extern cvar_t v_glslgamma;
250 extern cvar_t v_glslgamma_2d;
252 extern qboolean v_flipped_state;
254 r_framebufferstate_t r_fb;
256 /// shadow volume bsp struct with automatically growing nodes buffer
259 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
290 typedef struct r_qwskincache_s
292 char name[MAX_QPATH];
293 skinframe_t *skinframe;
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
310 const float r_d3dscreenvertex3f[12] =
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
321 for (i = 0;i < verts;i++)
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
335 for (i = 0;i < verts;i++)
345 // FIXME: move this to client?
348 if (gamemode == GAME_NEHAHRA)
350 Cvar_Set("gl_fogenable", "0");
351 Cvar_Set("gl_fogdensity", "0.2");
352 Cvar_Set("gl_fogred", "0.3");
353 Cvar_Set("gl_foggreen", "0.3");
354 Cvar_Set("gl_fogblue", "0.3");
356 r_refdef.fog_density = 0;
357 r_refdef.fog_red = 0;
358 r_refdef.fog_green = 0;
359 r_refdef.fog_blue = 0;
360 r_refdef.fog_alpha = 1;
361 r_refdef.fog_start = 0;
362 r_refdef.fog_end = 16384;
363 r_refdef.fog_height = 1<<30;
364 r_refdef.fog_fadedepth = 128;
365 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
368 static void R_BuildBlankTextures(void)
370 unsigned char data[4];
371 data[2] = 128; // normal X
372 data[1] = 128; // normal Y
373 data[0] = 255; // normal Z
374 data[3] = 255; // height
375 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 static void R_BuildNoTexture(void)
396 unsigned char pix[16][16][4];
397 // this makes a light grey/dark grey checkerboard texture
398 for (y = 0;y < 16;y++)
400 for (x = 0;x < 16;x++)
402 if ((y < 8) ^ (x < 8))
418 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
421 static void R_BuildWhiteCube(void)
423 unsigned char data[6*1*1*4];
424 memset(data, 255, sizeof(data));
425 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
428 static void R_BuildNormalizationCube(void)
432 vec_t s, t, intensity;
435 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436 for (side = 0;side < 6;side++)
438 for (y = 0;y < NORMSIZE;y++)
440 for (x = 0;x < NORMSIZE;x++)
442 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
478 intensity = 127.0f / sqrt(DotProduct(v, v));
479 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482 data[((side*64+y)*64+x)*4+3] = 255;
486 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
490 static void R_BuildFogTexture(void)
494 unsigned char data1[FOGWIDTH][4];
495 //unsigned char data2[FOGWIDTH][4];
498 r_refdef.fogmasktable_start = r_refdef.fog_start;
499 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500 r_refdef.fogmasktable_range = r_refdef.fogrange;
501 r_refdef.fogmasktable_density = r_refdef.fog_density;
503 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506 d = (x * r - r_refdef.fogmasktable_start);
507 if(developer_extra.integer)
508 Con_DPrintf("%f ", d);
510 if (r_fog_exp2.integer)
511 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514 if(developer_extra.integer)
515 Con_DPrintf(" : %f ", alpha);
516 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517 if(developer_extra.integer)
518 Con_DPrintf(" = %f\n", alpha);
519 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
522 for (x = 0;x < FOGWIDTH;x++)
524 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529 //data2[x][0] = 255 - b;
530 //data2[x][1] = 255 - b;
531 //data2[x][2] = 255 - b;
534 if (r_texture_fogattenuation)
536 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
546 static void R_BuildFogHeightTexture(void)
548 unsigned char *inpixels;
556 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557 if (r_refdef.fogheighttexturename[0])
558 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
561 r_refdef.fog_height_tablesize = 0;
562 if (r_texture_fogheighttexture)
563 R_FreeTexture(r_texture_fogheighttexture);
564 r_texture_fogheighttexture = NULL;
565 if (r_refdef.fog_height_table2d)
566 Mem_Free(r_refdef.fog_height_table2d);
567 r_refdef.fog_height_table2d = NULL;
568 if (r_refdef.fog_height_table1d)
569 Mem_Free(r_refdef.fog_height_table1d);
570 r_refdef.fog_height_table1d = NULL;
574 r_refdef.fog_height_tablesize = size;
575 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579 // LordHavoc: now the magic - what is that table2d for? it is a cooked
580 // average fog color table accounting for every fog layer between a point
581 // and the camera. (Note: attenuation is handled separately!)
582 for (y = 0;y < size;y++)
584 for (x = 0;x < size;x++)
590 for (j = x;j <= y;j++)
592 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
598 for (j = x;j >= y;j--)
600 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
611 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
614 //=======================================================================================================================================================
616 static const char *builtinshaderstrings[] =
618 #include "shader_glsl.h"
622 const char *builtinhlslshaderstrings[] =
624 #include "shader_hlsl.h"
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
631 //=======================================================================================================================================================
633 typedef struct shaderpermutationinfo_s
638 shaderpermutationinfo_t;
640 typedef struct shadermodeinfo_s
642 const char *filename;
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {"#define USEDIFFUSE\n", " diffuse"},
652 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653 {"#define USEVIEWTINT\n", " viewtint"},
654 {"#define USECOLORMAPPING\n", " colormapping"},
655 {"#define USESATURATION\n", " saturation"},
656 {"#define USEFOGINSIDE\n", " foginside"},
657 {"#define USEFOGOUTSIDE\n", " fogoutside"},
658 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660 {"#define USEGAMMARAMPS\n", " gammaramps"},
661 {"#define USECUBEFILTER\n", " cubefilter"},
662 {"#define USEGLOW\n", " glow"},
663 {"#define USEBLOOM\n", " bloom"},
664 {"#define USESPECULAR\n", " specular"},
665 {"#define USEPOSTPROCESSING\n", " postprocessing"},
666 {"#define USEREFLECTION\n", " reflection"},
667 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
671 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673 {"#define USEALPHAKILL\n", " alphakill"},
674 {"#define USEREFLECTCUBE\n", " reflectcube"},
675 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676 {"#define USEBOUNCEGRID\n", " bouncegrid"},
677 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
678 {"#define USETRIPPY\n", " trippy"},
679 {"#define USEDEPTHRGB\n", " depthrgb"},
680 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
681 {"#define USESKELETAL\n", " skeletal"}
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
687 {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688 {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689 {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690 {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691 {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692 {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693 {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
697 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
698 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
699 {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
700 {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
701 {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
702 {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703 {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
708 {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709 {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710 {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711 {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712 {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713 {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714 {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720 {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721 {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722 {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723 {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724 {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
727 struct r_glsl_permutation_s;
728 typedef struct r_glsl_permutation_s
731 struct r_glsl_permutation_s *hashnext;
733 unsigned int permutation;
735 /// indicates if we have tried compiling this permutation already
737 /// 0 if compilation failed
739 // texture units assigned to each detected uniform
740 int tex_Texture_First;
741 int tex_Texture_Second;
742 int tex_Texture_GammaRamps;
743 int tex_Texture_Normal;
744 int tex_Texture_Color;
745 int tex_Texture_Gloss;
746 int tex_Texture_Glow;
747 int tex_Texture_SecondaryNormal;
748 int tex_Texture_SecondaryColor;
749 int tex_Texture_SecondaryGloss;
750 int tex_Texture_SecondaryGlow;
751 int tex_Texture_Pants;
752 int tex_Texture_Shirt;
753 int tex_Texture_FogHeightTexture;
754 int tex_Texture_FogMask;
755 int tex_Texture_Lightmap;
756 int tex_Texture_Deluxemap;
757 int tex_Texture_Attenuation;
758 int tex_Texture_Cube;
759 int tex_Texture_Refraction;
760 int tex_Texture_Reflection;
761 int tex_Texture_ShadowMap2D;
762 int tex_Texture_CubeProjection;
763 int tex_Texture_ScreenNormalMap;
764 int tex_Texture_ScreenDiffuse;
765 int tex_Texture_ScreenSpecular;
766 int tex_Texture_ReflectMask;
767 int tex_Texture_ReflectCube;
768 int tex_Texture_BounceGrid;
769 /// locations of detected uniforms in program object, or -1 if not found
770 int loc_Texture_First;
771 int loc_Texture_Second;
772 int loc_Texture_GammaRamps;
773 int loc_Texture_Normal;
774 int loc_Texture_Color;
775 int loc_Texture_Gloss;
776 int loc_Texture_Glow;
777 int loc_Texture_SecondaryNormal;
778 int loc_Texture_SecondaryColor;
779 int loc_Texture_SecondaryGloss;
780 int loc_Texture_SecondaryGlow;
781 int loc_Texture_Pants;
782 int loc_Texture_Shirt;
783 int loc_Texture_FogHeightTexture;
784 int loc_Texture_FogMask;
785 int loc_Texture_Lightmap;
786 int loc_Texture_Deluxemap;
787 int loc_Texture_Attenuation;
788 int loc_Texture_Cube;
789 int loc_Texture_Refraction;
790 int loc_Texture_Reflection;
791 int loc_Texture_ShadowMap2D;
792 int loc_Texture_CubeProjection;
793 int loc_Texture_ScreenNormalMap;
794 int loc_Texture_ScreenDiffuse;
795 int loc_Texture_ScreenSpecular;
796 int loc_Texture_ReflectMask;
797 int loc_Texture_ReflectCube;
798 int loc_Texture_BounceGrid;
800 int loc_BloomBlur_Parameters;
802 int loc_Color_Ambient;
803 int loc_Color_Diffuse;
804 int loc_Color_Specular;
808 int loc_DeferredColor_Ambient;
809 int loc_DeferredColor_Diffuse;
810 int loc_DeferredColor_Specular;
811 int loc_DeferredMod_Diffuse;
812 int loc_DeferredMod_Specular;
813 int loc_DistortScaleRefractReflect;
816 int loc_FogHeightFade;
818 int loc_FogPlaneViewDist;
819 int loc_FogRangeRecip;
822 int loc_LightPosition;
823 int loc_OffsetMapping_ScaleSteps;
824 int loc_OffsetMapping_LodDistance;
825 int loc_OffsetMapping_Bias;
827 int loc_ReflectColor;
828 int loc_ReflectFactor;
829 int loc_ReflectOffset;
830 int loc_RefractColor;
832 int loc_ScreenCenterRefractReflect;
833 int loc_ScreenScaleRefractReflect;
834 int loc_ScreenToDepth;
835 int loc_ShadowMap_Parameters;
836 int loc_ShadowMap_TextureScale;
837 int loc_SpecularPower;
838 int loc_Skeletal_Transform12;
843 int loc_ViewTintColor;
845 int loc_ModelToLight;
847 int loc_BackgroundTexMatrix;
848 int loc_ModelViewProjectionMatrix;
849 int loc_ModelViewMatrix;
850 int loc_PixelToScreenTexCoord;
851 int loc_ModelToReflectCube;
852 int loc_ShadowMapMatrix;
853 int loc_BloomColorSubtract;
854 int loc_NormalmapScrollBlend;
855 int loc_BounceGridMatrix;
856 int loc_BounceGridIntensity;
857 /// uniform block bindings
858 int ubibind_Skeletal_Transform12_UniformBlock;
859 /// uniform block indices
860 int ubiloc_Skeletal_Transform12_UniformBlock;
862 r_glsl_permutation_t;
864 #define SHADERPERMUTATION_HASHSIZE 256
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
871 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
877 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
879 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
880 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
881 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
882 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
883 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
885 #define SHADERSTATICPARMS_COUNT 13
887 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
888 static int shaderstaticparms_count = 0;
890 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
891 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
893 extern qboolean r_shadow_shadowmapsampler;
894 extern int r_shadow_shadowmappcf;
895 qboolean R_CompileShader_CheckStaticParms(void)
897 static int r_compileshader_staticparms_save[1];
898 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
899 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
902 if (r_glsl_saturation_redcompensate.integer)
903 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
904 if (r_glsl_vertextextureblend_usebothalphas.integer)
905 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
906 if (r_shadow_glossexact.integer)
907 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
908 if (r_glsl_postprocess.integer)
910 if (r_glsl_postprocess_uservec1_enable.integer)
911 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
912 if (r_glsl_postprocess_uservec2_enable.integer)
913 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
914 if (r_glsl_postprocess_uservec3_enable.integer)
915 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
916 if (r_glsl_postprocess_uservec4_enable.integer)
917 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
919 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
920 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
922 if (r_shadow_shadowmapsampler)
923 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
924 if (r_shadow_shadowmappcf > 1)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
926 else if (r_shadow_shadowmappcf)
927 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
928 if (r_celshading.integer)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
930 if (r_celoutlines.integer)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
933 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
936 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
937 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
938 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
940 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
941 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
943 shaderstaticparms_count = 0;
946 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
947 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
948 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
949 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
950 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
951 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
952 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
953 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
954 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
955 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
956 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
957 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
958 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
961 /// information about each possible shader permutation
962 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
963 /// currently selected permutation
964 r_glsl_permutation_t *r_glsl_permutation;
965 /// storage for permutations linked in the hash table
966 memexpandablearray_t r_glsl_permutationarray;
968 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
970 //unsigned int hashdepth = 0;
971 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
972 r_glsl_permutation_t *p;
973 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
975 if (p->mode == mode && p->permutation == permutation)
977 //if (hashdepth > 10)
978 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
983 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
985 p->permutation = permutation;
986 p->hashnext = r_glsl_permutationhash[mode][hashindex];
987 r_glsl_permutationhash[mode][hashindex] = p;
988 //if (hashdepth > 10)
989 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
993 static char *R_ShaderStrCat(const char **strings)
996 const char **p = strings;
999 for (p = strings;(t = *p);p++)
1002 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1004 for (p = strings;(t = *p);p++)
1014 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1017 if (!filename || !filename[0])
1019 // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1020 if (!strcmp(filename, "glsl/default.glsl"))
1023 return R_ShaderStrCat(builtinshaderstrings);
1024 if (!glslshaderstring)
1026 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1027 if (glslshaderstring)
1028 Con_DPrintf("Loading shaders from file %s...\n", filename);
1030 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1032 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1033 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1034 return shaderstring;
1036 if (!strcmp(filename, "hlsl/default.hlsl"))
1039 return R_ShaderStrCat(builtinhlslshaderstrings);
1040 if (!hlslshaderstring)
1042 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1043 if (hlslshaderstring)
1044 Con_DPrintf("Loading shaders from file %s...\n", filename);
1046 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1048 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1049 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1050 return shaderstring;
1052 // we don't have builtin strings for any other files
1055 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1058 if (printfromdisknotice)
1059 Con_DPrintf("from disk %s... ", filename);
1060 return shaderstring;
1062 return shaderstring;
1065 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1070 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1072 char permutationname[256];
1073 int vertstrings_count = 0;
1074 int geomstrings_count = 0;
1075 int fragstrings_count = 0;
1076 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1077 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1078 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1085 permutationname[0] = 0;
1086 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1088 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1090 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1091 if(vid.support.glshaderversion >= 140)
1093 vertstrings_list[vertstrings_count++] = "#version 140\n";
1094 geomstrings_list[geomstrings_count++] = "#version 140\n";
1095 fragstrings_list[fragstrings_count++] = "#version 140\n";
1096 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1097 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1098 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1100 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1101 else if(vid.support.glshaderversion >= 130)
1103 vertstrings_list[vertstrings_count++] = "#version 130\n";
1104 geomstrings_list[geomstrings_count++] = "#version 130\n";
1105 fragstrings_list[fragstrings_count++] = "#version 130\n";
1106 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1107 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1108 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1111 // the first pretext is which type of shader to compile as
1112 // (later these will all be bound together as a program object)
1113 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1114 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1115 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1117 // the second pretext is the mode (for example a light source)
1118 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1119 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1120 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1121 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1123 // now add all the permutation pretexts
1124 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1126 if (permutation & (1<<i))
1128 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1129 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1130 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1131 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1135 // keep line numbers correct
1136 vertstrings_list[vertstrings_count++] = "\n";
1137 geomstrings_list[geomstrings_count++] = "\n";
1138 fragstrings_list[fragstrings_count++] = "\n";
1143 R_CompileShader_AddStaticParms(mode, permutation);
1144 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1145 vertstrings_count += shaderstaticparms_count;
1146 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1147 geomstrings_count += shaderstaticparms_count;
1148 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149 fragstrings_count += shaderstaticparms_count;
1151 // now append the shader text itself
1152 vertstrings_list[vertstrings_count++] = sourcestring;
1153 geomstrings_list[geomstrings_count++] = sourcestring;
1154 fragstrings_list[fragstrings_count++] = sourcestring;
1156 // compile the shader program
1157 if (vertstrings_count + geomstrings_count + fragstrings_count)
1158 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1162 qglUseProgram(p->program);CHECKGLERROR
1163 // look up all the uniform variable names we care about, so we don't
1164 // have to look them up every time we set them
1169 GLint activeuniformindex = 0;
1170 GLint numactiveuniforms = 0;
1171 char uniformname[128];
1172 GLsizei uniformnamelength = 0;
1173 GLint uniformsize = 0;
1174 GLenum uniformtype = 0;
1175 memset(uniformname, 0, sizeof(uniformname));
1176 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1177 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1178 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1180 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1181 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1186 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1187 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1188 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1189 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1190 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1191 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1192 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1193 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1194 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1195 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1196 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1197 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1198 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1199 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1200 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1201 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1202 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1203 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1204 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1205 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1206 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1207 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1208 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1209 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1210 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1211 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1212 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1213 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1214 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1215 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1216 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1217 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1218 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1219 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1220 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1221 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1222 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1223 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1224 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1225 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1226 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1227 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1228 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1229 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1230 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1231 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1232 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1233 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1234 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1235 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1236 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1237 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1238 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1239 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1240 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1241 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1242 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1243 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1244 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1245 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1246 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1247 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1248 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1249 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1250 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1251 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1252 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1253 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1254 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1255 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1256 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1257 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1258 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1259 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1260 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1261 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1262 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1263 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1264 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1265 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1266 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1267 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1268 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1269 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1270 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1271 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1272 // initialize the samplers to refer to the texture units we use
1273 p->tex_Texture_First = -1;
1274 p->tex_Texture_Second = -1;
1275 p->tex_Texture_GammaRamps = -1;
1276 p->tex_Texture_Normal = -1;
1277 p->tex_Texture_Color = -1;
1278 p->tex_Texture_Gloss = -1;
1279 p->tex_Texture_Glow = -1;
1280 p->tex_Texture_SecondaryNormal = -1;
1281 p->tex_Texture_SecondaryColor = -1;
1282 p->tex_Texture_SecondaryGloss = -1;
1283 p->tex_Texture_SecondaryGlow = -1;
1284 p->tex_Texture_Pants = -1;
1285 p->tex_Texture_Shirt = -1;
1286 p->tex_Texture_FogHeightTexture = -1;
1287 p->tex_Texture_FogMask = -1;
1288 p->tex_Texture_Lightmap = -1;
1289 p->tex_Texture_Deluxemap = -1;
1290 p->tex_Texture_Attenuation = -1;
1291 p->tex_Texture_Cube = -1;
1292 p->tex_Texture_Refraction = -1;
1293 p->tex_Texture_Reflection = -1;
1294 p->tex_Texture_ShadowMap2D = -1;
1295 p->tex_Texture_CubeProjection = -1;
1296 p->tex_Texture_ScreenNormalMap = -1;
1297 p->tex_Texture_ScreenDiffuse = -1;
1298 p->tex_Texture_ScreenSpecular = -1;
1299 p->tex_Texture_ReflectMask = -1;
1300 p->tex_Texture_ReflectCube = -1;
1301 p->tex_Texture_BounceGrid = -1;
1302 // bind the texture samplers in use
1304 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1305 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1306 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1307 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1308 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1309 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1310 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1311 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1312 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1313 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1314 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1315 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1316 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1317 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1318 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1319 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1320 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1321 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1322 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1323 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1324 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1325 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1326 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1327 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1328 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1329 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1330 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1331 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1332 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1333 // get the uniform block indices so we can bind them
1334 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1335 if (vid.support.arb_uniform_buffer_object)
1336 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1339 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1340 // clear the uniform block bindings
1341 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1342 // bind the uniform blocks in use
1344 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1345 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1347 // we're done compiling and setting up the shader, at least until it is used
1349 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1352 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1356 Mem_Free(sourcestring);
1359 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1361 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1362 if (r_glsl_permutation != perm)
1364 r_glsl_permutation = perm;
1365 if (!r_glsl_permutation->program)
1367 if (!r_glsl_permutation->compiled)
1369 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1370 R_GLSL_CompilePermutation(perm, mode, permutation);
1372 if (!r_glsl_permutation->program)
1374 // remove features until we find a valid permutation
1376 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1378 // reduce i more quickly whenever it would not remove any bits
1379 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1380 if (!(permutation & j))
1383 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1384 if (!r_glsl_permutation->compiled)
1385 R_GLSL_CompilePermutation(perm, mode, permutation);
1386 if (r_glsl_permutation->program)
1389 if (i >= SHADERPERMUTATION_COUNT)
1391 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1392 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1393 qglUseProgram(0);CHECKGLERROR
1394 return; // no bit left to clear, entire mode is broken
1399 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1401 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1402 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1403 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1411 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1412 extern D3DCAPS9 vid_d3d9caps;
1415 struct r_hlsl_permutation_s;
1416 typedef struct r_hlsl_permutation_s
1418 /// hash lookup data
1419 struct r_hlsl_permutation_s *hashnext;
1421 unsigned int permutation;
1423 /// indicates if we have tried compiling this permutation already
1425 /// NULL if compilation failed
1426 IDirect3DVertexShader9 *vertexshader;
1427 IDirect3DPixelShader9 *pixelshader;
1429 r_hlsl_permutation_t;
1431 typedef enum D3DVSREGISTER_e
1433 D3DVSREGISTER_TexMatrix = 0, // float4x4
1434 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1435 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1436 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1437 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1438 D3DVSREGISTER_ModelToLight = 20, // float4x4
1439 D3DVSREGISTER_EyePosition = 24,
1440 D3DVSREGISTER_FogPlane = 25,
1441 D3DVSREGISTER_LightDir = 26,
1442 D3DVSREGISTER_LightPosition = 27,
1446 typedef enum D3DPSREGISTER_e
1448 D3DPSREGISTER_Alpha = 0,
1449 D3DPSREGISTER_BloomBlur_Parameters = 1,
1450 D3DPSREGISTER_ClientTime = 2,
1451 D3DPSREGISTER_Color_Ambient = 3,
1452 D3DPSREGISTER_Color_Diffuse = 4,
1453 D3DPSREGISTER_Color_Specular = 5,
1454 D3DPSREGISTER_Color_Glow = 6,
1455 D3DPSREGISTER_Color_Pants = 7,
1456 D3DPSREGISTER_Color_Shirt = 8,
1457 D3DPSREGISTER_DeferredColor_Ambient = 9,
1458 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1459 D3DPSREGISTER_DeferredColor_Specular = 11,
1460 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1461 D3DPSREGISTER_DeferredMod_Specular = 13,
1462 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1463 D3DPSREGISTER_EyePosition = 15, // unused
1464 D3DPSREGISTER_FogColor = 16,
1465 D3DPSREGISTER_FogHeightFade = 17,
1466 D3DPSREGISTER_FogPlane = 18,
1467 D3DPSREGISTER_FogPlaneViewDist = 19,
1468 D3DPSREGISTER_FogRangeRecip = 20,
1469 D3DPSREGISTER_LightColor = 21,
1470 D3DPSREGISTER_LightDir = 22, // unused
1471 D3DPSREGISTER_LightPosition = 23,
1472 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1473 D3DPSREGISTER_PixelSize = 25,
1474 D3DPSREGISTER_ReflectColor = 26,
1475 D3DPSREGISTER_ReflectFactor = 27,
1476 D3DPSREGISTER_ReflectOffset = 28,
1477 D3DPSREGISTER_RefractColor = 29,
1478 D3DPSREGISTER_Saturation = 30,
1479 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1480 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1481 D3DPSREGISTER_ScreenToDepth = 33,
1482 D3DPSREGISTER_ShadowMap_Parameters = 34,
1483 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1484 D3DPSREGISTER_SpecularPower = 36,
1485 D3DPSREGISTER_UserVec1 = 37,
1486 D3DPSREGISTER_UserVec2 = 38,
1487 D3DPSREGISTER_UserVec3 = 39,
1488 D3DPSREGISTER_UserVec4 = 40,
1489 D3DPSREGISTER_ViewTintColor = 41,
1490 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1491 D3DPSREGISTER_BloomColorSubtract = 43,
1492 D3DPSREGISTER_ViewToLight = 44, // float4x4
1493 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1494 D3DPSREGISTER_NormalmapScrollBlend = 52,
1495 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1496 D3DPSREGISTER_OffsetMapping_Bias = 54,
1501 /// information about each possible shader permutation
1502 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1503 /// currently selected permutation
1504 r_hlsl_permutation_t *r_hlsl_permutation;
1505 /// storage for permutations linked in the hash table
1506 memexpandablearray_t r_hlsl_permutationarray;
1508 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1510 //unsigned int hashdepth = 0;
1511 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1512 r_hlsl_permutation_t *p;
1513 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1515 if (p->mode == mode && p->permutation == permutation)
1517 //if (hashdepth > 10)
1518 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1523 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1525 p->permutation = permutation;
1526 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1527 r_hlsl_permutationhash[mode][hashindex] = p;
1528 //if (hashdepth > 10)
1529 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1534 //#include <d3dx9shader.h>
1535 //#include <d3dx9mesh.h>
1537 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1539 DWORD *vsbin = NULL;
1540 DWORD *psbin = NULL;
1541 fs_offset_t vsbinsize;
1542 fs_offset_t psbinsize;
1543 // IDirect3DVertexShader9 *vs = NULL;
1544 // IDirect3DPixelShader9 *ps = NULL;
1545 ID3DXBuffer *vslog = NULL;
1546 ID3DXBuffer *vsbuffer = NULL;
1547 ID3DXConstantTable *vsconstanttable = NULL;
1548 ID3DXBuffer *pslog = NULL;
1549 ID3DXBuffer *psbuffer = NULL;
1550 ID3DXConstantTable *psconstanttable = NULL;
1553 char temp[MAX_INPUTLINE];
1554 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1556 qboolean debugshader = gl_paranoid.integer != 0;
1557 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1558 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1561 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1562 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1564 if ((!vsbin && vertstring) || (!psbin && fragstring))
1566 const char* dllnames_d3dx9 [] =
1590 dllhandle_t d3dx9_dll = NULL;
1591 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1592 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1593 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1594 dllfunction_t d3dx9_dllfuncs[] =
1596 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1597 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1598 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1601 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1602 #ifndef ID3DXBuffer_GetBufferPointer
1603 #if !defined(__cplusplus) || defined(CINTERFACE)
1604 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1605 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1606 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1608 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1609 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1610 #define ID3DXBuffer_Release(p) (p)->Release()
1613 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1615 DWORD shaderflags = 0;
1617 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1618 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1619 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1620 if (vertstring && vertstring[0])
1624 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1625 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1628 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1631 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1632 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1633 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1634 ID3DXBuffer_Release(vsbuffer);
1638 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1639 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1640 ID3DXBuffer_Release(vslog);
1643 if (fragstring && fragstring[0])
1647 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1648 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1651 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1654 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1655 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1656 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1657 ID3DXBuffer_Release(psbuffer);
1661 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1662 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1663 ID3DXBuffer_Release(pslog);
1666 Sys_UnloadLibrary(&d3dx9_dll);
1669 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1673 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1674 if (FAILED(vsresult))
1675 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1676 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1677 if (FAILED(psresult))
1678 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1680 // free the shader data
1681 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1682 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1685 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1688 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1689 int vertstring_length = 0;
1690 int geomstring_length = 0;
1691 int fragstring_length = 0;
1694 char *vertstring, *geomstring, *fragstring;
1695 char permutationname[256];
1696 char cachename[256];
1697 int vertstrings_count = 0;
1698 int geomstrings_count = 0;
1699 int fragstrings_count = 0;
1700 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1701 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1702 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1707 p->vertexshader = NULL;
1708 p->pixelshader = NULL;
1710 permutationname[0] = 0;
1712 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1714 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1715 strlcat(cachename, "hlsl/", sizeof(cachename));
1717 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1718 vertstrings_count = 0;
1719 geomstrings_count = 0;
1720 fragstrings_count = 0;
1721 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1722 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1723 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1725 // the first pretext is which type of shader to compile as
1726 // (later these will all be bound together as a program object)
1727 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1728 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1729 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1731 // the second pretext is the mode (for example a light source)
1732 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1733 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1734 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1735 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1736 strlcat(cachename, modeinfo->name, sizeof(cachename));
1738 // now add all the permutation pretexts
1739 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1741 if (permutation & (1<<i))
1743 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1744 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1745 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1746 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1747 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1751 // keep line numbers correct
1752 vertstrings_list[vertstrings_count++] = "\n";
1753 geomstrings_list[geomstrings_count++] = "\n";
1754 fragstrings_list[fragstrings_count++] = "\n";
1759 R_CompileShader_AddStaticParms(mode, permutation);
1760 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1761 vertstrings_count += shaderstaticparms_count;
1762 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1763 geomstrings_count += shaderstaticparms_count;
1764 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1765 fragstrings_count += shaderstaticparms_count;
1767 // replace spaces in the cachename with _ characters
1768 for (i = 0;cachename[i];i++)
1769 if (cachename[i] == ' ')
1772 // now append the shader text itself
1773 vertstrings_list[vertstrings_count++] = sourcestring;
1774 geomstrings_list[geomstrings_count++] = sourcestring;
1775 fragstrings_list[fragstrings_count++] = sourcestring;
1777 vertstring_length = 0;
1778 for (i = 0;i < vertstrings_count;i++)
1779 vertstring_length += strlen(vertstrings_list[i]);
1780 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1781 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1782 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1784 geomstring_length = 0;
1785 for (i = 0;i < geomstrings_count;i++)
1786 geomstring_length += strlen(geomstrings_list[i]);
1787 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1788 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1789 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1791 fragstring_length = 0;
1792 for (i = 0;i < fragstrings_count;i++)
1793 fragstring_length += strlen(fragstrings_list[i]);
1794 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1795 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1796 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1798 // try to load the cached shader, or generate one
1799 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1801 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1802 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1804 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1808 Mem_Free(vertstring);
1810 Mem_Free(geomstring);
1812 Mem_Free(fragstring);
1814 Mem_Free(sourcestring);
1817 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1818 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1819 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1820 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1821 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1822 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1824 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1825 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1826 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1827 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1828 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1829 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1831 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1833 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1834 if (r_hlsl_permutation != perm)
1836 r_hlsl_permutation = perm;
1837 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1839 if (!r_hlsl_permutation->compiled)
1840 R_HLSL_CompilePermutation(perm, mode, permutation);
1841 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1843 // remove features until we find a valid permutation
1845 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1847 // reduce i more quickly whenever it would not remove any bits
1848 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1849 if (!(permutation & j))
1852 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1853 if (!r_hlsl_permutation->compiled)
1854 R_HLSL_CompilePermutation(perm, mode, permutation);
1855 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1858 if (i >= SHADERPERMUTATION_COUNT)
1860 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1861 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1862 return; // no bit left to clear, entire mode is broken
1866 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1867 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1869 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1870 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1871 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1875 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1877 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1878 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1879 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1880 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1883 void R_GLSL_Restart_f(void)
1885 unsigned int i, limit;
1886 if (glslshaderstring)
1887 Mem_Free(glslshaderstring);
1888 glslshaderstring = NULL;
1889 if (hlslshaderstring)
1890 Mem_Free(hlslshaderstring);
1891 hlslshaderstring = NULL;
1892 switch(vid.renderpath)
1894 case RENDERPATH_D3D9:
1897 r_hlsl_permutation_t *p;
1898 r_hlsl_permutation = NULL;
1899 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1900 for (i = 0;i < limit;i++)
1902 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1904 if (p->vertexshader)
1905 IDirect3DVertexShader9_Release(p->vertexshader);
1907 IDirect3DPixelShader9_Release(p->pixelshader);
1908 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1911 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1915 case RENDERPATH_D3D10:
1916 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918 case RENDERPATH_D3D11:
1919 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1921 case RENDERPATH_GL20:
1922 case RENDERPATH_GLES2:
1924 r_glsl_permutation_t *p;
1925 r_glsl_permutation = NULL;
1926 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1927 for (i = 0;i < limit;i++)
1929 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1931 GL_Backend_FreeProgram(p->program);
1932 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1935 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1938 case RENDERPATH_GL11:
1939 case RENDERPATH_GL13:
1940 case RENDERPATH_GLES1:
1942 case RENDERPATH_SOFT:
1947 static void R_GLSL_DumpShader_f(void)
1949 int i, language, mode, dupe;
1951 shadermodeinfo_t *modeinfo;
1954 for (language = 0;language < 2;language++)
1956 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1957 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1959 // don't dump the same file multiple times (most or all shaders come from the same file)
1960 for (dupe = mode - 1;dupe >= 0;dupe--)
1961 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1965 text = R_GetShaderText(modeinfo[mode].filename, false, true);
1968 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1971 FS_Print(file, "/* The engine may define the following macros:\n");
1972 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1973 for (i = 0;i < SHADERMODE_COUNT;i++)
1974 FS_Print(file, modeinfo[i].pretext);
1975 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1976 FS_Print(file, shaderpermutationinfo[i].pretext);
1977 FS_Print(file, "*/\n");
1978 FS_Print(file, text);
1980 Con_Printf("%s written\n", modeinfo[mode].filename);
1983 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1989 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1991 unsigned int permutation = 0;
1992 if (r_trippy.integer && !notrippy)
1993 permutation |= SHADERPERMUTATION_TRIPPY;
1994 permutation |= SHADERPERMUTATION_VIEWTINT;
1996 permutation |= SHADERPERMUTATION_DIFFUSE;
1998 permutation |= SHADERPERMUTATION_SPECULAR;
1999 if (texturemode == GL_MODULATE)
2000 permutation |= SHADERPERMUTATION_COLORMAPPING;
2001 else if (texturemode == GL_ADD)
2002 permutation |= SHADERPERMUTATION_GLOW;
2003 else if (texturemode == GL_DECAL)
2004 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2005 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2006 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2007 if (suppresstexalpha)
2008 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2010 texturemode = GL_MODULATE;
2011 if (vid.allowalphatocoverage)
2012 GL_AlphaToCoverage(false);
2013 switch (vid.renderpath)
2015 case RENDERPATH_D3D9:
2017 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2018 R_Mesh_TexBind(GL20TU_FIRST , first );
2019 R_Mesh_TexBind(GL20TU_SECOND, second);
2020 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2021 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2024 case RENDERPATH_D3D10:
2025 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2027 case RENDERPATH_D3D11:
2028 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2030 case RENDERPATH_GL20:
2031 case RENDERPATH_GLES2:
2032 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2033 if (r_glsl_permutation->tex_Texture_First >= 0)
2034 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2035 if (r_glsl_permutation->tex_Texture_Second >= 0)
2036 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2037 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2038 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2040 case RENDERPATH_GL13:
2041 case RENDERPATH_GLES1:
2042 R_Mesh_TexBind(0, first );
2043 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2044 R_Mesh_TexMatrix(0, NULL);
2045 R_Mesh_TexBind(1, second);
2048 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2049 R_Mesh_TexMatrix(1, NULL);
2052 case RENDERPATH_GL11:
2053 R_Mesh_TexBind(0, first );
2054 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2055 R_Mesh_TexMatrix(0, NULL);
2057 case RENDERPATH_SOFT:
2058 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2059 R_Mesh_TexBind(GL20TU_FIRST , first );
2060 R_Mesh_TexBind(GL20TU_SECOND, second);
2065 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2067 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2070 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2072 unsigned int permutation = 0;
2073 if (r_trippy.integer && !notrippy)
2074 permutation |= SHADERPERMUTATION_TRIPPY;
2076 permutation |= SHADERPERMUTATION_DEPTHRGB;
2078 permutation |= SHADERPERMUTATION_SKELETAL;
2080 if (vid.allowalphatocoverage)
2081 GL_AlphaToCoverage(false);
2082 switch (vid.renderpath)
2084 case RENDERPATH_D3D9:
2086 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2089 case RENDERPATH_D3D10:
2090 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2092 case RENDERPATH_D3D11:
2093 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2095 case RENDERPATH_GL20:
2096 case RENDERPATH_GLES2:
2097 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2098 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2099 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2102 case RENDERPATH_GL13:
2103 case RENDERPATH_GLES1:
2104 R_Mesh_TexBind(0, 0);
2105 R_Mesh_TexBind(1, 0);
2107 case RENDERPATH_GL11:
2108 R_Mesh_TexBind(0, 0);
2110 case RENDERPATH_SOFT:
2111 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2116 extern qboolean r_shadow_usingdeferredprepass;
2117 extern rtexture_t *r_shadow_attenuationgradienttexture;
2118 extern rtexture_t *r_shadow_attenuation2dtexture;
2119 extern rtexture_t *r_shadow_attenuation3dtexture;
2120 extern qboolean r_shadow_usingshadowmap2d;
2121 extern qboolean r_shadow_usingshadowmaportho;
2122 extern float r_shadow_shadowmap_texturescale[2];
2123 extern float r_shadow_shadowmap_parameters[4];
2124 extern qboolean r_shadow_shadowmapvsdct;
2125 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2126 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2127 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2128 extern matrix4x4_t r_shadow_shadowmapmatrix;
2129 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2130 extern int r_shadow_prepass_width;
2131 extern int r_shadow_prepass_height;
2132 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2133 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2134 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2135 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2137 #define BLENDFUNC_ALLOWS_COLORMOD 1
2138 #define BLENDFUNC_ALLOWS_FOG 2
2139 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2140 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2141 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2142 static int R_BlendFuncFlags(int src, int dst)
2146 // a blendfunc allows colormod if:
2147 // a) it can never keep the destination pixel invariant, or
2148 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2149 // this is to prevent unintended side effects from colormod
2151 // a blendfunc allows fog if:
2152 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2153 // this is to prevent unintended side effects from fog
2155 // these checks are the output of fogeval.pl
2157 r |= BLENDFUNC_ALLOWS_COLORMOD;
2158 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2159 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2160 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2161 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2162 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2163 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2164 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2165 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2166 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2167 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2168 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2169 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2170 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2171 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2172 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2173 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2174 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2175 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2177 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2178 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2183 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2185 // select a permutation of the lighting shader appropriate to this
2186 // combination of texture, entity, light source, and fogging, only use the
2187 // minimum features necessary to avoid wasting rendering time in the
2188 // fragment shader on features that are not being used
2189 unsigned int permutation = 0;
2190 unsigned int mode = 0;
2192 static float dummy_colormod[3] = {1, 1, 1};
2193 float *colormod = rsurface.colormod;
2195 matrix4x4_t tempmatrix;
2196 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2197 if (r_trippy.integer && !notrippy)
2198 permutation |= SHADERPERMUTATION_TRIPPY;
2199 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2200 permutation |= SHADERPERMUTATION_ALPHAKILL;
2201 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2202 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2203 if (rsurfacepass == RSURFPASS_BACKGROUND)
2205 // distorted background
2206 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2208 mode = SHADERMODE_WATER;
2209 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2210 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2211 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2213 // this is the right thing to do for wateralpha
2214 GL_BlendFunc(GL_ONE, GL_ZERO);
2215 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2219 // this is the right thing to do for entity alpha
2220 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2221 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2224 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2226 mode = SHADERMODE_REFRACTION;
2227 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2228 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2229 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2230 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2234 mode = SHADERMODE_GENERIC;
2235 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2236 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2237 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2239 if (vid.allowalphatocoverage)
2240 GL_AlphaToCoverage(false);
2242 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2244 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2246 switch(rsurface.texture->offsetmapping)
2248 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2249 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2250 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2251 case OFFSETMAPPING_OFF: break;
2254 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2255 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2256 // normalmap (deferred prepass), may use alpha test on diffuse
2257 mode = SHADERMODE_DEFERREDGEOMETRY;
2258 GL_BlendFunc(GL_ONE, GL_ZERO);
2259 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2260 if (vid.allowalphatocoverage)
2261 GL_AlphaToCoverage(false);
2263 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2265 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2267 switch(rsurface.texture->offsetmapping)
2269 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2270 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2271 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2272 case OFFSETMAPPING_OFF: break;
2275 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2276 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2277 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2278 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2280 mode = SHADERMODE_LIGHTSOURCE;
2281 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2282 permutation |= SHADERPERMUTATION_CUBEFILTER;
2283 if (diffusescale > 0)
2284 permutation |= SHADERPERMUTATION_DIFFUSE;
2285 if (specularscale > 0)
2286 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2287 if (r_refdef.fogenabled)
2288 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2289 if (rsurface.texture->colormapping)
2290 permutation |= SHADERPERMUTATION_COLORMAPPING;
2291 if (r_shadow_usingshadowmap2d)
2293 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2294 if(r_shadow_shadowmapvsdct)
2295 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2297 if (r_shadow_shadowmap2ddepthbuffer)
2298 permutation |= SHADERPERMUTATION_DEPTHRGB;
2300 if (rsurface.texture->reflectmasktexture)
2301 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2302 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2303 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2304 if (vid.allowalphatocoverage)
2305 GL_AlphaToCoverage(false);
2307 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2309 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2311 switch(rsurface.texture->offsetmapping)
2313 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2314 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2316 case OFFSETMAPPING_OFF: break;
2319 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2320 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2321 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2322 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2323 // unshaded geometry (fullbright or ambient model lighting)
2324 mode = SHADERMODE_FLATCOLOR;
2325 ambientscale = diffusescale = specularscale = 0;
2326 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2327 permutation |= SHADERPERMUTATION_GLOW;
2328 if (r_refdef.fogenabled)
2329 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2330 if (rsurface.texture->colormapping)
2331 permutation |= SHADERPERMUTATION_COLORMAPPING;
2332 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2334 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2335 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2337 if (r_shadow_shadowmap2ddepthbuffer)
2338 permutation |= SHADERPERMUTATION_DEPTHRGB;
2340 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2341 permutation |= SHADERPERMUTATION_REFLECTION;
2342 if (rsurface.texture->reflectmasktexture)
2343 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2344 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2345 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2346 // when using alphatocoverage, we don't need alphakill
2347 if (vid.allowalphatocoverage)
2349 if (r_transparent_alphatocoverage.integer)
2351 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2352 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2355 GL_AlphaToCoverage(false);
2358 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2360 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2362 switch(rsurface.texture->offsetmapping)
2364 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2365 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2366 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2367 case OFFSETMAPPING_OFF: break;
2370 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2371 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2372 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2373 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2374 // directional model lighting
2375 mode = SHADERMODE_LIGHTDIRECTION;
2376 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2377 permutation |= SHADERPERMUTATION_GLOW;
2378 permutation |= SHADERPERMUTATION_DIFFUSE;
2379 if (specularscale > 0)
2380 permutation |= SHADERPERMUTATION_SPECULAR;
2381 if (r_refdef.fogenabled)
2382 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2383 if (rsurface.texture->colormapping)
2384 permutation |= SHADERPERMUTATION_COLORMAPPING;
2385 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2387 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2388 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2390 if (r_shadow_shadowmap2ddepthbuffer)
2391 permutation |= SHADERPERMUTATION_DEPTHRGB;
2393 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2394 permutation |= SHADERPERMUTATION_REFLECTION;
2395 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2396 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2397 if (rsurface.texture->reflectmasktexture)
2398 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2399 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2401 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2402 if (r_shadow_bouncegriddirectional)
2403 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2405 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2406 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2407 // when using alphatocoverage, we don't need alphakill
2408 if (vid.allowalphatocoverage)
2410 if (r_transparent_alphatocoverage.integer)
2412 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2413 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2416 GL_AlphaToCoverage(false);
2419 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2421 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2423 switch(rsurface.texture->offsetmapping)
2425 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2426 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2427 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2428 case OFFSETMAPPING_OFF: break;
2431 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2432 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2434 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2435 // ambient model lighting
2436 mode = SHADERMODE_LIGHTDIRECTION;
2437 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2438 permutation |= SHADERPERMUTATION_GLOW;
2439 if (r_refdef.fogenabled)
2440 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2441 if (rsurface.texture->colormapping)
2442 permutation |= SHADERPERMUTATION_COLORMAPPING;
2443 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2445 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2446 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2448 if (r_shadow_shadowmap2ddepthbuffer)
2449 permutation |= SHADERPERMUTATION_DEPTHRGB;
2451 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2452 permutation |= SHADERPERMUTATION_REFLECTION;
2453 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2454 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2455 if (rsurface.texture->reflectmasktexture)
2456 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2457 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2459 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2460 if (r_shadow_bouncegriddirectional)
2461 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2463 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2464 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2465 // when using alphatocoverage, we don't need alphakill
2466 if (vid.allowalphatocoverage)
2468 if (r_transparent_alphatocoverage.integer)
2470 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2471 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2474 GL_AlphaToCoverage(false);
2479 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2481 switch(rsurface.texture->offsetmapping)
2483 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2484 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2485 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2486 case OFFSETMAPPING_OFF: break;
2489 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2490 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2491 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2492 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2494 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2495 permutation |= SHADERPERMUTATION_GLOW;
2496 if (r_refdef.fogenabled)
2497 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2498 if (rsurface.texture->colormapping)
2499 permutation |= SHADERPERMUTATION_COLORMAPPING;
2500 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2502 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2503 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2505 if (r_shadow_shadowmap2ddepthbuffer)
2506 permutation |= SHADERPERMUTATION_DEPTHRGB;
2508 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2509 permutation |= SHADERPERMUTATION_REFLECTION;
2510 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2511 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2512 if (rsurface.texture->reflectmasktexture)
2513 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2514 if (FAKELIGHT_ENABLED)
2516 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2517 mode = SHADERMODE_FAKELIGHT;
2518 permutation |= SHADERPERMUTATION_DIFFUSE;
2519 if (specularscale > 0)
2520 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2522 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2524 // deluxemapping (light direction texture)
2525 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2526 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2528 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2529 permutation |= SHADERPERMUTATION_DIFFUSE;
2530 if (specularscale > 0)
2531 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2533 else if (r_glsl_deluxemapping.integer >= 2)
2535 // fake deluxemapping (uniform light direction in tangentspace)
2536 if (rsurface.uselightmaptexture)
2537 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2539 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2540 permutation |= SHADERPERMUTATION_DIFFUSE;
2541 if (specularscale > 0)
2542 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2544 else if (rsurface.uselightmaptexture)
2546 // ordinary lightmapping (q1bsp, q3bsp)
2547 mode = SHADERMODE_LIGHTMAP;
2551 // ordinary vertex coloring (q3bsp)
2552 mode = SHADERMODE_VERTEXCOLOR;
2554 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2556 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2557 if (r_shadow_bouncegriddirectional)
2558 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2560 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2561 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2562 // when using alphatocoverage, we don't need alphakill
2563 if (vid.allowalphatocoverage)
2565 if (r_transparent_alphatocoverage.integer)
2567 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2568 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2571 GL_AlphaToCoverage(false);
2574 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2575 colormod = dummy_colormod;
2576 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2577 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2578 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2579 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2580 switch(vid.renderpath)
2582 case RENDERPATH_D3D9:
2584 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2585 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2586 R_SetupShader_SetPermutationHLSL(mode, permutation);
2587 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2588 if (mode == SHADERMODE_LIGHTSOURCE)
2590 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2591 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2595 if (mode == SHADERMODE_LIGHTDIRECTION)
2597 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2600 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2601 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2602 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2603 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2604 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2606 if (mode == SHADERMODE_LIGHTSOURCE)
2608 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2609 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2610 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2611 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2612 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2614 // additive passes are only darkened by fog, not tinted
2615 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2616 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2620 if (mode == SHADERMODE_FLATCOLOR)
2622 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2624 else if (mode == SHADERMODE_LIGHTDIRECTION)
2626 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2627 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2628 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2629 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2630 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2631 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2632 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2636 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2637 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2638 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2639 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2640 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2642 // additive passes are only darkened by fog, not tinted
2643 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2644 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2646 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2647 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2648 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2649 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2650 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2651 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2652 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2653 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2654 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2655 if (mode == SHADERMODE_WATER)
2656 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2658 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2659 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2660 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2661 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2662 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2663 if (rsurface.texture->pantstexture)
2664 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2666 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2667 if (rsurface.texture->shirttexture)
2668 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2670 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2671 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2672 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2673 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2674 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2675 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2676 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2677 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2678 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2679 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2681 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2682 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2683 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2684 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2686 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2687 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2688 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2689 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2690 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2691 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2692 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2693 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2694 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2695 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2696 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2697 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2698 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2699 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2700 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2701 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2702 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2703 if (rsurfacepass == RSURFPASS_BACKGROUND)
2705 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2706 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2707 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2711 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2713 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2714 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2715 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2716 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2718 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2719 if (rsurface.rtlight)
2721 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2722 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2727 case RENDERPATH_D3D10:
2728 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2730 case RENDERPATH_D3D11:
2731 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2733 case RENDERPATH_GL20:
2734 case RENDERPATH_GLES2:
2735 if (!vid.useinterleavedarrays)
2737 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2738 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2739 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2740 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2741 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2742 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2743 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2744 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2745 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2746 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2747 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2751 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2752 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2754 // this has to be after RSurf_PrepareVerticesForBatch
2755 if (rsurface.batchskeletaltransform3x4buffer)
2756 permutation |= SHADERPERMUTATION_SKELETAL;
2757 R_SetupShader_SetPermutationGLSL(mode, permutation);
2758 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2759 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2761 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2762 if (mode == SHADERMODE_LIGHTSOURCE)
2764 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2765 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2766 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2767 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2768 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2769 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2771 // additive passes are only darkened by fog, not tinted
2772 if (r_glsl_permutation->loc_FogColor >= 0)
2773 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2774 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2778 if (mode == SHADERMODE_FLATCOLOR)
2780 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2782 else if (mode == SHADERMODE_LIGHTDIRECTION)
2784 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2785 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2786 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2787 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2788 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2789 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2790 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2794 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2795 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2796 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2797 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2798 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2800 // additive passes are only darkened by fog, not tinted
2801 if (r_glsl_permutation->loc_FogColor >= 0)
2803 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2804 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2806 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2808 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2809 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2810 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2811 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2812 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2813 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2814 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2815 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2816 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2818 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2819 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2820 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2821 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2822 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2824 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2825 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2826 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2827 if (r_glsl_permutation->loc_Color_Pants >= 0)
2829 if (rsurface.texture->pantstexture)
2830 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2832 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2834 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2836 if (rsurface.texture->shirttexture)
2837 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2839 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2841 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2842 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2843 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2844 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2845 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2846 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2847 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2848 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2849 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2851 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2852 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2853 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2854 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2855 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2856 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2858 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2859 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2860 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2861 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2862 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2863 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2864 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2865 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2866 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2867 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2868 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2869 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2870 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2871 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2872 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2873 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2874 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2875 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2876 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2877 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2878 if (rsurfacepass == RSURFPASS_BACKGROUND)
2880 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2881 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2882 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2886 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2888 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2889 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2890 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2891 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2893 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2894 if (rsurface.rtlight)
2896 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2897 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2900 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2903 case RENDERPATH_GL11:
2904 case RENDERPATH_GL13:
2905 case RENDERPATH_GLES1:
2907 case RENDERPATH_SOFT:
2908 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2909 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2910 R_SetupShader_SetPermutationSoft(mode, permutation);
2911 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2912 if (mode == SHADERMODE_LIGHTSOURCE)
2914 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2915 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2916 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2917 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2918 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2919 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2921 // additive passes are only darkened by fog, not tinted
2922 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2923 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2927 if (mode == SHADERMODE_FLATCOLOR)
2929 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2931 else if (mode == SHADERMODE_LIGHTDIRECTION)
2933 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2934 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2935 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2936 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2937 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2938 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2939 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2943 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2944 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2945 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2946 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2947 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2949 // additive passes are only darkened by fog, not tinted
2950 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2951 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2953 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2954 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2955 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2956 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2957 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2958 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2959 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2960 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2961 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2962 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2964 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2965 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2966 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2967 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2968 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2970 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2971 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2972 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2973 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2975 if (rsurface.texture->pantstexture)
2976 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2978 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2980 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2982 if (rsurface.texture->shirttexture)
2983 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2985 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2987 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2988 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2989 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2990 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2991 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2992 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2993 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2994 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2995 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2997 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2998 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2999 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3000 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3002 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3003 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3004 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3005 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3006 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3007 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3008 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3009 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3010 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3011 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3012 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3013 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3014 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3015 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3016 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3017 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3018 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3019 if (rsurfacepass == RSURFPASS_BACKGROUND)
3021 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3022 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3023 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3027 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3029 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3030 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3031 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3032 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3034 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3035 if (rsurface.rtlight)
3037 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3038 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3045 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3047 // select a permutation of the lighting shader appropriate to this
3048 // combination of texture, entity, light source, and fogging, only use the
3049 // minimum features necessary to avoid wasting rendering time in the
3050 // fragment shader on features that are not being used
3051 unsigned int permutation = 0;
3052 unsigned int mode = 0;
3053 const float *lightcolorbase = rtlight->currentcolor;
3054 float ambientscale = rtlight->ambientscale;
3055 float diffusescale = rtlight->diffusescale;
3056 float specularscale = rtlight->specularscale;
3057 // this is the location of the light in view space
3058 vec3_t viewlightorigin;
3059 // this transforms from view space (camera) to light space (cubemap)
3060 matrix4x4_t viewtolight;
3061 matrix4x4_t lighttoview;
3062 float viewtolight16f[16];
3064 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3065 if (rtlight->currentcubemap != r_texture_whitecube)
3066 permutation |= SHADERPERMUTATION_CUBEFILTER;
3067 if (diffusescale > 0)
3068 permutation |= SHADERPERMUTATION_DIFFUSE;
3069 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3070 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3071 if (r_shadow_usingshadowmap2d)
3073 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3074 if (r_shadow_shadowmapvsdct)
3075 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3077 if (r_shadow_shadowmap2ddepthbuffer)
3078 permutation |= SHADERPERMUTATION_DEPTHRGB;
3080 if (vid.allowalphatocoverage)
3081 GL_AlphaToCoverage(false);
3082 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3083 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3084 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3085 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3086 switch(vid.renderpath)
3088 case RENDERPATH_D3D9:
3090 R_SetupShader_SetPermutationHLSL(mode, permutation);
3091 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3092 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3093 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3094 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3095 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3096 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3097 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3098 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3099 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3100 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3102 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3103 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3104 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3105 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3106 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3109 case RENDERPATH_D3D10:
3110 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3112 case RENDERPATH_D3D11:
3113 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3115 case RENDERPATH_GL20:
3116 case RENDERPATH_GLES2:
3117 R_SetupShader_SetPermutationGLSL(mode, permutation);
3118 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3119 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3120 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3121 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3122 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3123 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3124 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3125 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3126 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3127 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3129 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3130 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3131 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3132 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3133 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3135 case RENDERPATH_GL11:
3136 case RENDERPATH_GL13:
3137 case RENDERPATH_GLES1:
3139 case RENDERPATH_SOFT:
3140 R_SetupShader_SetPermutationGLSL(mode, permutation);
3141 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3142 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3143 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3144 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3145 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3146 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3147 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3148 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3149 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3150 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3152 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3153 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3154 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3155 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3156 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3161 #define SKINFRAME_HASH 1024
3165 int loadsequence; // incremented each level change
3166 memexpandablearray_t array;
3167 skinframe_t *hash[SKINFRAME_HASH];
3170 r_skinframe_t r_skinframe;
3172 void R_SkinFrame_PrepareForPurge(void)
3174 r_skinframe.loadsequence++;
3175 // wrap it without hitting zero
3176 if (r_skinframe.loadsequence >= 200)
3177 r_skinframe.loadsequence = 1;
3180 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3184 // mark the skinframe as used for the purging code
3185 skinframe->loadsequence = r_skinframe.loadsequence;
3188 void R_SkinFrame_Purge(void)
3192 for (i = 0;i < SKINFRAME_HASH;i++)
3194 for (s = r_skinframe.hash[i];s;s = s->next)
3196 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3198 if (s->merged == s->base)
3200 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3201 R_PurgeTexture(s->stain );s->stain = NULL;
3202 R_PurgeTexture(s->merged);s->merged = NULL;
3203 R_PurgeTexture(s->base );s->base = NULL;
3204 R_PurgeTexture(s->pants );s->pants = NULL;
3205 R_PurgeTexture(s->shirt );s->shirt = NULL;
3206 R_PurgeTexture(s->nmap );s->nmap = NULL;
3207 R_PurgeTexture(s->gloss );s->gloss = NULL;
3208 R_PurgeTexture(s->glow );s->glow = NULL;
3209 R_PurgeTexture(s->fog );s->fog = NULL;
3210 R_PurgeTexture(s->reflect);s->reflect = NULL;
3211 s->loadsequence = 0;
3217 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3219 char basename[MAX_QPATH];
3221 Image_StripImageExtension(name, basename, sizeof(basename));
3223 if( last == NULL ) {
3225 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3226 item = r_skinframe.hash[hashindex];
3231 // linearly search through the hash bucket
3232 for( ; item ; item = item->next ) {
3233 if( !strcmp( item->basename, basename ) ) {
3240 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3244 char basename[MAX_QPATH];
3246 Image_StripImageExtension(name, basename, sizeof(basename));
3248 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3249 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3250 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3254 rtexture_t *dyntexture;
3255 // check whether its a dynamic texture
3256 dyntexture = CL_GetDynTexture( basename );
3257 if (!add && !dyntexture)
3259 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3260 memset(item, 0, sizeof(*item));
3261 strlcpy(item->basename, basename, sizeof(item->basename));
3262 item->base = dyntexture; // either NULL or dyntexture handle
3263 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3264 item->comparewidth = comparewidth;
3265 item->compareheight = compareheight;
3266 item->comparecrc = comparecrc;
3267 item->next = r_skinframe.hash[hashindex];
3268 r_skinframe.hash[hashindex] = item;
3270 else if (textureflags & TEXF_FORCE_RELOAD)
3272 rtexture_t *dyntexture;
3273 // check whether its a dynamic texture
3274 dyntexture = CL_GetDynTexture( basename );
3275 if (!add && !dyntexture)
3277 if (item->merged == item->base)
3278 item->merged = NULL;
3279 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3280 R_PurgeTexture(item->stain );item->stain = NULL;
3281 R_PurgeTexture(item->merged);item->merged = NULL;
3282 R_PurgeTexture(item->base );item->base = NULL;
3283 R_PurgeTexture(item->pants );item->pants = NULL;
3284 R_PurgeTexture(item->shirt );item->shirt = NULL;
3285 R_PurgeTexture(item->nmap );item->nmap = NULL;
3286 R_PurgeTexture(item->gloss );item->gloss = NULL;
3287 R_PurgeTexture(item->glow );item->glow = NULL;
3288 R_PurgeTexture(item->fog );item->fog = NULL;
3289 R_PurgeTexture(item->reflect);item->reflect = NULL;
3290 item->loadsequence = 0;
3292 else if( item->base == NULL )
3294 rtexture_t *dyntexture;
3295 // check whether its a dynamic texture
3296 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3297 dyntexture = CL_GetDynTexture( basename );
3298 item->base = dyntexture; // either NULL or dyntexture handle
3301 R_SkinFrame_MarkUsed(item);
3305 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3307 unsigned long long avgcolor[5], wsum; \
3315 for(pix = 0; pix < cnt; ++pix) \
3318 for(comp = 0; comp < 3; ++comp) \
3320 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3323 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3325 for(comp = 0; comp < 3; ++comp) \
3326 avgcolor[comp] += getpixel * w; \
3329 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3330 avgcolor[4] += getpixel; \
3332 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3334 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3335 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3336 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3337 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3340 extern cvar_t gl_picmip;
3341 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3344 unsigned char *pixels;
3345 unsigned char *bumppixels;
3346 unsigned char *basepixels = NULL;
3347 int basepixels_width = 0;
3348 int basepixels_height = 0;
3349 skinframe_t *skinframe;
3350 rtexture_t *ddsbase = NULL;
3351 qboolean ddshasalpha = false;
3352 float ddsavgcolor[4];
3353 char basename[MAX_QPATH];
3354 int miplevel = R_PicmipForFlags(textureflags);
3355 int savemiplevel = miplevel;
3359 if (cls.state == ca_dedicated)
3362 // return an existing skinframe if already loaded
3363 // if loading of the first image fails, don't make a new skinframe as it
3364 // would cause all future lookups of this to be missing
3365 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3366 if (skinframe && skinframe->base)
3369 Image_StripImageExtension(name, basename, sizeof(basename));
3371 // check for DDS texture file first
3372 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3374 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3375 if (basepixels == NULL)
3379 // FIXME handle miplevel
3381 if (developer_loading.integer)
3382 Con_Printf("loading skin \"%s\"\n", name);
3384 // we've got some pixels to store, so really allocate this new texture now
3386 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3387 textureflags &= ~TEXF_FORCE_RELOAD;
3388 skinframe->stain = NULL;
3389 skinframe->merged = NULL;
3390 skinframe->base = NULL;
3391 skinframe->pants = NULL;
3392 skinframe->shirt = NULL;
3393 skinframe->nmap = NULL;
3394 skinframe->gloss = NULL;
3395 skinframe->glow = NULL;
3396 skinframe->fog = NULL;
3397 skinframe->reflect = NULL;
3398 skinframe->hasalpha = false;
3402 skinframe->base = ddsbase;
3403 skinframe->hasalpha = ddshasalpha;
3404 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3405 if (r_loadfog && skinframe->hasalpha)
3406 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3407 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3411 basepixels_width = image_width;
3412 basepixels_height = image_height;
3413 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3414 if (textureflags & TEXF_ALPHA)
3416 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3418 if (basepixels[j] < 255)
3420 skinframe->hasalpha = true;
3424 if (r_loadfog && skinframe->hasalpha)
3426 // has transparent pixels
3427 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3428 for (j = 0;j < image_width * image_height * 4;j += 4)
3433 pixels[j+3] = basepixels[j+3];
3435 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3439 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3441 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3442 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3443 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3444 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3445 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3451 mymiplevel = savemiplevel;
3452 if (r_loadnormalmap)
3453 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3454 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3456 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3457 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3458 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3459 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3462 // _norm is the name used by tenebrae and has been adopted as standard
3463 if (r_loadnormalmap && skinframe->nmap == NULL)
3465 mymiplevel = savemiplevel;
3466 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3468 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3472 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3474 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3475 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3476 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3478 Mem_Free(bumppixels);
3480 else if (r_shadow_bumpscale_basetexture.value > 0)
3482 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3483 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3484 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3488 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3489 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3493 // _luma is supported only for tenebrae compatibility
3494 // _glow is the preferred name
3495 mymiplevel = savemiplevel;
3496 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3498 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3500 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3501 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3503 Mem_Free(pixels);pixels = NULL;
3506 mymiplevel = savemiplevel;
3507 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3509 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3511 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3512 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3518 mymiplevel = savemiplevel;
3519 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3521 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3523 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3524 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3530 mymiplevel = savemiplevel;
3531 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3533 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3535 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3536 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3542 mymiplevel = savemiplevel;
3543 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3545 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3547 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3548 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3555 Mem_Free(basepixels);
3560 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3561 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3564 unsigned char *temp1, *temp2;
3565 skinframe_t *skinframe;
3568 if (cls.state == ca_dedicated)
3571 // if already loaded just return it, otherwise make a new skinframe
3572 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3573 if (skinframe->base)
3575 textureflags &= ~TEXF_FORCE_RELOAD;
3577 skinframe->stain = NULL;
3578 skinframe->merged = NULL;
3579 skinframe->base = NULL;
3580 skinframe->pants = NULL;
3581 skinframe->shirt = NULL;
3582 skinframe->nmap = NULL;
3583 skinframe->gloss = NULL;
3584 skinframe->glow = NULL;
3585 skinframe->fog = NULL;
3586 skinframe->reflect = NULL;
3587 skinframe->hasalpha = false;
3589 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3593 if (developer_loading.integer)
3594 Con_Printf("loading 32bit skin \"%s\"\n", name);
3596 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3598 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3599 temp2 = temp1 + width * height * 4;
3600 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3601 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3604 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3605 if (textureflags & TEXF_ALPHA)
3607 for (i = 3;i < width * height * 4;i += 4)
3609 if (skindata[i] < 255)
3611 skinframe->hasalpha = true;
3615 if (r_loadfog && skinframe->hasalpha)
3617 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3618 memcpy(fogpixels, skindata, width * height * 4);
3619 for (i = 0;i < width * height * 4;i += 4)
3620 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3621 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3622 Mem_Free(fogpixels);
3626 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3627 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3632 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3636 skinframe_t *skinframe;
3638 if (cls.state == ca_dedicated)
3641 // if already loaded just return it, otherwise make a new skinframe
3642 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3643 if (skinframe->base)
3645 //textureflags &= ~TEXF_FORCE_RELOAD;
3647 skinframe->stain = NULL;
3648 skinframe->merged = NULL;
3649 skinframe->base = NULL;
3650 skinframe->pants = NULL;
3651 skinframe->shirt = NULL;
3652 skinframe->nmap = NULL;
3653 skinframe->gloss = NULL;
3654 skinframe->glow = NULL;
3655 skinframe->fog = NULL;
3656 skinframe->reflect = NULL;
3657 skinframe->hasalpha = false;
3659 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3663 if (developer_loading.integer)
3664 Con_Printf("loading quake skin \"%s\"\n", name);
3666 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3667 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3668 memcpy(skinframe->qpixels, skindata, width*height);
3669 skinframe->qwidth = width;
3670 skinframe->qheight = height;
3673 for (i = 0;i < width * height;i++)
3674 featuresmask |= palette_featureflags[skindata[i]];
3676 skinframe->hasalpha = false;
3677 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3678 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3679 skinframe->qgeneratemerged = true;
3680 skinframe->qgeneratebase = skinframe->qhascolormapping;
3681 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3683 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3684 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3689 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3693 unsigned char *skindata;
3696 if (!skinframe->qpixels)
3699 if (!skinframe->qhascolormapping)
3700 colormapped = false;
3704 if (!skinframe->qgeneratebase)
3709 if (!skinframe->qgeneratemerged)
3713 width = skinframe->qwidth;
3714 height = skinframe->qheight;
3715 skindata = skinframe->qpixels;
3717 if (skinframe->qgeneratenmap)
3719 unsigned char *temp1, *temp2;
3720 skinframe->qgeneratenmap = false;
3721 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3722 temp2 = temp1 + width * height * 4;
3723 // use either a custom palette or the quake palette
3724 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3725 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3726 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3730 if (skinframe->qgenerateglow)
3732 skinframe->qgenerateglow = false;
3733 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3738 skinframe->qgeneratebase = false;
3739 skinframe->base = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3740 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3741 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3745 skinframe->qgeneratemerged = false;
3746 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3749 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3751 Mem_Free(skinframe->qpixels);
3752 skinframe->qpixels = NULL;
3756 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3759 skinframe_t *skinframe;
3762 if (cls.state == ca_dedicated)
3765 // if already loaded just return it, otherwise make a new skinframe
3766 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3767 if (skinframe->base)
3769 textureflags &= ~TEXF_FORCE_RELOAD;
3771 skinframe->stain = NULL;
3772 skinframe->merged = NULL;
3773 skinframe->base = NULL;
3774 skinframe->pants = NULL;
3775 skinframe->shirt = NULL;
3776 skinframe->nmap = NULL;
3777 skinframe->gloss = NULL;
3778 skinframe->glow = NULL;
3779 skinframe->fog = NULL;
3780 skinframe->reflect = NULL;
3781 skinframe->hasalpha = false;
3783 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3787 if (developer_loading.integer)
3788 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3790 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3791 if (textureflags & TEXF_ALPHA)
3793 for (i = 0;i < width * height;i++)
3795 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3797 skinframe->hasalpha = true;
3801 if (r_loadfog && skinframe->hasalpha)
3802 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3805 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3806 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3811 skinframe_t *R_SkinFrame_LoadMissing(void)
3813 skinframe_t *skinframe;
3815 if (cls.state == ca_dedicated)
3818 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3819 skinframe->stain = NULL;
3820 skinframe->merged = NULL;
3821 skinframe->base = NULL;
3822 skinframe->pants = NULL;
3823 skinframe->shirt = NULL;
3824 skinframe->nmap = NULL;
3825 skinframe->gloss = NULL;
3826 skinframe->glow = NULL;
3827 skinframe->fog = NULL;
3828 skinframe->reflect = NULL;
3829 skinframe->hasalpha = false;
3831 skinframe->avgcolor[0] = rand() / RAND_MAX;
3832 skinframe->avgcolor[1] = rand() / RAND_MAX;
3833 skinframe->avgcolor[2] = rand() / RAND_MAX;
3834 skinframe->avgcolor[3] = 1;
3839 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3840 typedef struct suffixinfo_s
3843 qboolean flipx, flipy, flipdiagonal;
3846 static suffixinfo_t suffix[3][6] =
3849 {"px", false, false, false},
3850 {"nx", false, false, false},
3851 {"py", false, false, false},
3852 {"ny", false, false, false},
3853 {"pz", false, false, false},
3854 {"nz", false, false, false}
3857 {"posx", false, false, false},
3858 {"negx", false, false, false},
3859 {"posy", false, false, false},
3860 {"negy", false, false, false},
3861 {"posz", false, false, false},
3862 {"negz", false, false, false}
3865 {"rt", true, false, true},
3866 {"lf", false, true, true},
3867 {"ft", true, true, false},
3868 {"bk", false, false, false},
3869 {"up", true, false, true},
3870 {"dn", true, false, true}
3874 static int componentorder[4] = {0, 1, 2, 3};
3876 static rtexture_t *R_LoadCubemap(const char *basename)
3878 int i, j, cubemapsize;
3879 unsigned char *cubemappixels, *image_buffer;
3880 rtexture_t *cubemaptexture;
3882 // must start 0 so the first loadimagepixels has no requested width/height
3884 cubemappixels = NULL;
3885 cubemaptexture = NULL;
3886 // keep trying different suffix groups (posx, px, rt) until one loads
3887 for (j = 0;j < 3 && !cubemappixels;j++)
3889 // load the 6 images in the suffix group
3890 for (i = 0;i < 6;i++)
3892 // generate an image name based on the base and and suffix
3893 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3895 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3897 // an image loaded, make sure width and height are equal
3898 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3900 // if this is the first image to load successfully, allocate the cubemap memory
3901 if (!cubemappixels && image_width >= 1)
3903 cubemapsize = image_width;
3904 // note this clears to black, so unavailable sides are black
3905 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3907 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3909 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3912 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3914 Mem_Free(image_buffer);
3918 // if a cubemap loaded, upload it
3921 if (developer_loading.integer)
3922 Con_Printf("loading cubemap \"%s\"\n", basename);
3924 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3925 Mem_Free(cubemappixels);
3929 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3930 if (developer_loading.integer)
3932 Con_Printf("(tried tried images ");
3933 for (j = 0;j < 3;j++)
3934 for (i = 0;i < 6;i++)
3935 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3936 Con_Print(" and was unable to find any of them).\n");
3939 return cubemaptexture;
3942 rtexture_t *R_GetCubemap(const char *basename)
3945 for (i = 0;i < r_texture_numcubemaps;i++)
3946 if (r_texture_cubemaps[i] != NULL)
3947 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3948 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3949 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3950 return r_texture_whitecube;
3951 r_texture_numcubemaps++;
3952 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3953 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3954 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3955 return r_texture_cubemaps[i]->texture;
3958 static void R_Main_FreeViewCache(void)
3960 if (r_refdef.viewcache.entityvisible)
3961 Mem_Free(r_refdef.viewcache.entityvisible);
3962 if (r_refdef.viewcache.world_pvsbits)
3963 Mem_Free(r_refdef.viewcache.world_pvsbits);
3964 if (r_refdef.viewcache.world_leafvisible)
3965 Mem_Free(r_refdef.viewcache.world_leafvisible);
3966 if (r_refdef.viewcache.world_surfacevisible)
3967 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3968 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3971 static void R_Main_ResizeViewCache(void)
3973 int numentities = r_refdef.scene.numentities;
3974 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3975 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3976 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3977 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3978 if (r_refdef.viewcache.maxentities < numentities)
3980 r_refdef.viewcache.maxentities = numentities;
3981 if (r_refdef.viewcache.entityvisible)
3982 Mem_Free(r_refdef.viewcache.entityvisible);
3983 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3985 if (r_refdef.viewcache.world_numclusters != numclusters)
3987 r_refdef.viewcache.world_numclusters = numclusters;
3988 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3989 if (r_refdef.viewcache.world_pvsbits)
3990 Mem_Free(r_refdef.viewcache.world_pvsbits);
3991 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3993 if (r_refdef.viewcache.world_numleafs != numleafs)
3995 r_refdef.viewcache.world_numleafs = numleafs;
3996 if (r_refdef.viewcache.world_leafvisible)
3997 Mem_Free(r_refdef.viewcache.world_leafvisible);
3998 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4000 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4002 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4003 if (r_refdef.viewcache.world_surfacevisible)
4004 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4005 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4009 extern rtexture_t *loadingscreentexture;
4010 static void gl_main_start(void)
4012 loadingscreentexture = NULL;
4013 r_texture_blanknormalmap = NULL;
4014 r_texture_white = NULL;
4015 r_texture_grey128 = NULL;
4016 r_texture_black = NULL;
4017 r_texture_whitecube = NULL;
4018 r_texture_normalizationcube = NULL;
4019 r_texture_fogattenuation = NULL;
4020 r_texture_fogheighttexture = NULL;
4021 r_texture_gammaramps = NULL;
4022 r_texture_numcubemaps = 0;
4023 r_uniformbufferalignment = 32;
4025 r_loaddds = r_texture_dds_load.integer != 0;
4026 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4028 switch(vid.renderpath)
4030 case RENDERPATH_GL20:
4031 case RENDERPATH_D3D9:
4032 case RENDERPATH_D3D10:
4033 case RENDERPATH_D3D11:
4034 case RENDERPATH_SOFT:
4035 case RENDERPATH_GLES2:
4036 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4037 Cvar_SetValueQuick(&gl_combine, 1);
4038 Cvar_SetValueQuick(&r_glsl, 1);
4039 r_loadnormalmap = true;
4042 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4043 if (vid.support.arb_uniform_buffer_object)
4044 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4047 case RENDERPATH_GL13:
4048 case RENDERPATH_GLES1:
4049 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4050 Cvar_SetValueQuick(&gl_combine, 1);
4051 Cvar_SetValueQuick(&r_glsl, 0);
4052 r_loadnormalmap = false;
4053 r_loadgloss = false;
4056 case RENDERPATH_GL11:
4057 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4058 Cvar_SetValueQuick(&gl_combine, 0);
4059 Cvar_SetValueQuick(&r_glsl, 0);
4060 r_loadnormalmap = false;
4061 r_loadgloss = false;
4067 R_FrameData_Reset();
4068 R_BufferData_Reset();
4072 memset(r_queries, 0, sizeof(r_queries));
4074 r_qwskincache = NULL;
4075 r_qwskincache_size = 0;
4077 // due to caching of texture_t references, the collision cache must be reset
4078 Collision_Cache_Reset(true);
4080 // set up r_skinframe loading system for textures
4081 memset(&r_skinframe, 0, sizeof(r_skinframe));
4082 r_skinframe.loadsequence = 1;
4083 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4085 r_main_texturepool = R_AllocTexturePool();
4086 R_BuildBlankTextures();
4088 if (vid.support.arb_texture_cube_map)
4091 R_BuildNormalizationCube();
4093 r_texture_fogattenuation = NULL;
4094 r_texture_fogheighttexture = NULL;
4095 r_texture_gammaramps = NULL;
4096 //r_texture_fogintensity = NULL;
4097 memset(&r_fb, 0, sizeof(r_fb));
4098 r_glsl_permutation = NULL;
4099 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4100 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4101 glslshaderstring = NULL;
4103 r_hlsl_permutation = NULL;
4104 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4105 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4107 hlslshaderstring = NULL;
4108 memset(&r_svbsp, 0, sizeof (r_svbsp));
4110 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4111 r_texture_numcubemaps = 0;
4113 r_refdef.fogmasktable_density = 0;
4116 // For Steelstorm Android
4117 // FIXME CACHE the program and reload
4118 // FIXME see possible combinations for SS:BR android
4119 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4120 R_SetupShader_SetPermutationGLSL(0, 12);
4121 R_SetupShader_SetPermutationGLSL(0, 13);
4122 R_SetupShader_SetPermutationGLSL(0, 8388621);
4123 R_SetupShader_SetPermutationGLSL(3, 0);
4124 R_SetupShader_SetPermutationGLSL(3, 2048);
4125 R_SetupShader_SetPermutationGLSL(5, 0);
4126 R_SetupShader_SetPermutationGLSL(5, 2);
4127 R_SetupShader_SetPermutationGLSL(5, 2048);
4128 R_SetupShader_SetPermutationGLSL(5, 8388608);
4129 R_SetupShader_SetPermutationGLSL(11, 1);
4130 R_SetupShader_SetPermutationGLSL(11, 2049);
4131 R_SetupShader_SetPermutationGLSL(11, 8193);
4132 R_SetupShader_SetPermutationGLSL(11, 10241);
4133 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4137 static void gl_main_shutdown(void)
4140 R_FrameData_Reset();
4141 R_BufferData_Reset();
4143 R_Main_FreeViewCache();
4145 switch(vid.renderpath)
4147 case RENDERPATH_GL11:
4148 case RENDERPATH_GL13:
4149 case RENDERPATH_GL20:
4150 case RENDERPATH_GLES1:
4151 case RENDERPATH_GLES2:
4152 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4154 qglDeleteQueriesARB(r_maxqueries, r_queries);
4157 case RENDERPATH_D3D9:
4158 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4160 case RENDERPATH_D3D10:
4161 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4163 case RENDERPATH_D3D11:
4164 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4166 case RENDERPATH_SOFT:
4172 memset(r_queries, 0, sizeof(r_queries));
4174 r_qwskincache = NULL;
4175 r_qwskincache_size = 0;
4177 // clear out the r_skinframe state
4178 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4179 memset(&r_skinframe, 0, sizeof(r_skinframe));
4182 Mem_Free(r_svbsp.nodes);
4183 memset(&r_svbsp, 0, sizeof (r_svbsp));
4184 R_FreeTexturePool(&r_main_texturepool);
4185 loadingscreentexture = NULL;
4186 r_texture_blanknormalmap = NULL;
4187 r_texture_white = NULL;
4188 r_texture_grey128 = NULL;
4189 r_texture_black = NULL;
4190 r_texture_whitecube = NULL;
4191 r_texture_normalizationcube = NULL;
4192 r_texture_fogattenuation = NULL;
4193 r_texture_fogheighttexture = NULL;
4194 r_texture_gammaramps = NULL;
4195 r_texture_numcubemaps = 0;
4196 //r_texture_fogintensity = NULL;
4197 memset(&r_fb, 0, sizeof(r_fb));
4200 r_glsl_permutation = NULL;
4201 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4202 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4203 glslshaderstring = NULL;
4205 r_hlsl_permutation = NULL;
4206 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4207 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4209 hlslshaderstring = NULL;
4212 static void gl_main_newmap(void)
4214 // FIXME: move this code to client
4215 char *entities, entname[MAX_QPATH];
4217 Mem_Free(r_qwskincache);
4218 r_qwskincache = NULL;
4219 r_qwskincache_size = 0;
4222 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4223 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4225 CL_ParseEntityLump(entities);
4229 if (cl.worldmodel->brush.entities)
4230 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4232 R_Main_FreeViewCache();
4234 R_FrameData_Reset();
4235 R_BufferData_Reset();
4238 void GL_Main_Init(void)
4241 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4243 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4244 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4245 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4246 if (gamemode == GAME_NEHAHRA)
4248 Cvar_RegisterVariable (&gl_fogenable);
4249 Cvar_RegisterVariable (&gl_fogdensity);
4250 Cvar_RegisterVariable (&gl_fogred);
4251 Cvar_RegisterVariable (&gl_foggreen);
4252 Cvar_RegisterVariable (&gl_fogblue);
4253 Cvar_RegisterVariable (&gl_fogstart);
4254 Cvar_RegisterVariable (&gl_fogend);
4255 Cvar_RegisterVariable (&gl_skyclip);
4257 Cvar_RegisterVariable(&r_motionblur);
4258 Cvar_RegisterVariable(&r_damageblur);
4259 Cvar_RegisterVariable(&r_motionblur_averaging);
4260 Cvar_RegisterVariable(&r_motionblur_randomize);
4261 Cvar_RegisterVariable(&r_motionblur_minblur);
4262 Cvar_RegisterVariable(&r_motionblur_maxblur);
4263 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4264 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4265 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4266 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4267 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4268 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4269 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4270 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4271 Cvar_RegisterVariable(&r_equalize_entities_by);
4272 Cvar_RegisterVariable(&r_equalize_entities_to);
4273 Cvar_RegisterVariable(&r_depthfirst);
4274 Cvar_RegisterVariable(&r_useinfinitefarclip);
4275 Cvar_RegisterVariable(&r_farclip_base);
4276 Cvar_RegisterVariable(&r_farclip_world);
4277 Cvar_RegisterVariable(&r_nearclip);
4278 Cvar_RegisterVariable(&r_deformvertexes);
4279 Cvar_RegisterVariable(&r_transparent);
4280 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4281 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4282 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4283 Cvar_RegisterVariable(&r_showoverdraw);
4284 Cvar_RegisterVariable(&r_showbboxes);
4285 Cvar_RegisterVariable(&r_showsurfaces);
4286 Cvar_RegisterVariable(&r_showtris);
4287 Cvar_RegisterVariable(&r_shownormals);
4288 Cvar_RegisterVariable(&r_showlighting);
4289 Cvar_RegisterVariable(&r_showshadowvolumes);
4290 Cvar_RegisterVariable(&r_showcollisionbrushes);
4291 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4292 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4293 Cvar_RegisterVariable(&r_showdisabledepthtest);
4294 Cvar_RegisterVariable(&r_drawportals);
4295 Cvar_RegisterVariable(&r_drawentities);
4296 Cvar_RegisterVariable(&r_draw2d);
4297 Cvar_RegisterVariable(&r_drawworld);
4298 Cvar_RegisterVariable(&r_cullentities_trace);
4299 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4300 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4301 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4302 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4303 Cvar_RegisterVariable(&r_sortentities);
4304 Cvar_RegisterVariable(&r_drawviewmodel);
4305 Cvar_RegisterVariable(&r_drawexteriormodel);
4306 Cvar_RegisterVariable(&r_speeds);
4307 Cvar_RegisterVariable(&r_fullbrights);
4308 Cvar_RegisterVariable(&r_wateralpha);
4309 Cvar_RegisterVariable(&r_dynamic);
4310 Cvar_RegisterVariable(&r_fakelight);
4311 Cvar_RegisterVariable(&r_fakelight_intensity);
4312 Cvar_RegisterVariable(&r_fullbright);
4313 Cvar_RegisterVariable(&r_shadows);
4314 Cvar_RegisterVariable(&r_shadows_darken);
4315 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4316 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4317 Cvar_RegisterVariable(&r_shadows_throwdistance);
4318 Cvar_RegisterVariable(&r_shadows_throwdirection);
4319 Cvar_RegisterVariable(&r_shadows_focus);
4320 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4321 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4322 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4323 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4324 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4325 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4326 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4327 Cvar_RegisterVariable(&r_fog_exp2);
4328 Cvar_RegisterVariable(&r_fog_clear);
4329 Cvar_RegisterVariable(&r_drawfog);
4330 Cvar_RegisterVariable(&r_transparentdepthmasking);
4331 Cvar_RegisterVariable(&r_transparent_sortmindist);
4332 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4333 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4334 Cvar_RegisterVariable(&r_texture_dds_load);
4335 Cvar_RegisterVariable(&r_texture_dds_save);
4336 Cvar_RegisterVariable(&r_textureunits);
4337 Cvar_RegisterVariable(&gl_combine);
4338 Cvar_RegisterVariable(&r_usedepthtextures);
4339 Cvar_RegisterVariable(&r_viewfbo);
4340 Cvar_RegisterVariable(&r_viewscale);
4341 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4342 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4343 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4344 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4345 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4346 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4347 Cvar_RegisterVariable(&r_glsl);
4348 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4349 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4350 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4351 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4352 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4353 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4354 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4355 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4356 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4357 Cvar_RegisterVariable(&r_glsl_postprocess);
4358 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4359 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4360 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4361 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4362 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4363 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4364 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4365 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4366 Cvar_RegisterVariable(&r_celshading);
4367 Cvar_RegisterVariable(&r_celoutlines);
4369 Cvar_RegisterVariable(&r_water);
4370 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4371 Cvar_RegisterVariable(&r_water_clippingplanebias);
4372 Cvar_RegisterVariable(&r_water_refractdistort);
4373 Cvar_RegisterVariable(&r_water_reflectdistort);
4374 Cvar_RegisterVariable(&r_water_scissormode);
4375 Cvar_RegisterVariable(&r_water_lowquality);
4376 Cvar_RegisterVariable(&r_water_hideplayer);
4377 Cvar_RegisterVariable(&r_water_fbo);
4379 Cvar_RegisterVariable(&r_lerpsprites);
4380 Cvar_RegisterVariable(&r_lerpmodels);
4381 Cvar_RegisterVariable(&r_lerplightstyles);
4382 Cvar_RegisterVariable(&r_waterscroll);
4383 Cvar_RegisterVariable(&r_bloom);
4384 Cvar_RegisterVariable(&r_bloom_colorscale);
4385 Cvar_RegisterVariable(&r_bloom_brighten);
4386 Cvar_RegisterVariable(&r_bloom_blur);
4387 Cvar_RegisterVariable(&r_bloom_resolution);
4388 Cvar_RegisterVariable(&r_bloom_colorexponent);
4389 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4390 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4391 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4392 Cvar_RegisterVariable(&r_hdr_glowintensity);
4393 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4394 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4395 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4396 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4397 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4398 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4399 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4400 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4401 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4402 Cvar_RegisterVariable(&developer_texturelogging);
4403 Cvar_RegisterVariable(&gl_lightmaps);
4404 Cvar_RegisterVariable(&r_test);
4405 Cvar_RegisterVariable(&r_batch_multidraw);
4406 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4407 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4408 Cvar_RegisterVariable(&r_glsl_skeletal);
4409 Cvar_RegisterVariable(&r_glsl_saturation);
4410 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4411 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4412 Cvar_RegisterVariable(&r_framedatasize);
4413 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4414 Cvar_RegisterVariable(&r_buffermegs[i]);
4415 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4416 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4417 Cvar_SetValue("r_fullbrights", 0);
4418 #ifdef DP_MOBILETOUCH
4419 // GLES devices have terrible depth precision in general, so...
4420 Cvar_SetValueQuick(&r_nearclip, 4);
4421 Cvar_SetValueQuick(&r_farclip_base, 4096);
4422 Cvar_SetValueQuick(&r_farclip_world, 0);
4423 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4425 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4428 void Render_Init(void)
4441 R_LightningBeams_Init();
4451 extern char *ENGINE_EXTENSIONS;
4454 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4455 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4456 gl_version = (const char *)qglGetString(GL_VERSION);
4457 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4461 if (!gl_platformextensions)
4462 gl_platformextensions = "";
4464 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4465 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4466 Con_Printf("GL_VERSION: %s\n", gl_version);
4467 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4468 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4470 VID_CheckExtensions();
4472 // LordHavoc: report supported extensions
4474 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4476 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4479 // clear to black (loading plaque will be seen over this)
4480 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4484 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4488 if (r_trippy.integer)
4490 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4492 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4495 p = r_refdef.view.frustum + i;
4500 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4504 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4508 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4512 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4516 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4520 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4524 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4528 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4536 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4540 if (r_trippy.integer)
4542 for (i = 0;i < numplanes;i++)
4549 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4553 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4557 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4561 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4565 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4569 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4573 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4577 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4585 //==================================================================================
4587 // LordHavoc: this stores temporary data used within the same frame
4589 typedef struct r_framedata_mem_s
4591 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4592 size_t size; // how much usable space
4593 size_t current; // how much space in use
4594 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4595 size_t wantedsize; // how much space was allocated
4596 unsigned char *data; // start of real data (16byte aligned)
4600 static r_framedata_mem_t *r_framedata_mem;
4602 void R_FrameData_Reset(void)
4604 while (r_framedata_mem)
4606 r_framedata_mem_t *next = r_framedata_mem->purge;
4607 Mem_Free(r_framedata_mem);
4608 r_framedata_mem = next;
4612 static void R_FrameData_Resize(qboolean mustgrow)
4615 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4616 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4617 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4619 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4620 newmem->wantedsize = wantedsize;
4621 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4622 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4623 newmem->current = 0;
4625 newmem->purge = r_framedata_mem;
4626 r_framedata_mem = newmem;
4630 void R_FrameData_NewFrame(void)
4632 R_FrameData_Resize(false);
4633 if (!r_framedata_mem)
4635 // if we ran out of space on the last frame, free the old memory now
4636 while (r_framedata_mem->purge)
4638 // repeatedly remove the second item in the list, leaving only head
4639 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4640 Mem_Free(r_framedata_mem->purge);
4641 r_framedata_mem->purge = next;
4643 // reset the current mem pointer
4644 r_framedata_mem->current = 0;
4645 r_framedata_mem->mark = 0;
4648 void *R_FrameData_Alloc(size_t size)
4653 // align to 16 byte boundary - the data pointer is already aligned, so we
4654 // only need to ensure the size of every allocation is also aligned
4655 size = (size + 15) & ~15;
4657 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4659 // emergency - we ran out of space, allocate more memory
4660 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4661 // this might not be a growing it, but we'll allocate another buffer every time
4662 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4663 R_FrameData_Resize(true);
4666 data = r_framedata_mem->data + r_framedata_mem->current;
4667 r_framedata_mem->current += size;
4669 // count the usage for stats
4670 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4671 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4673 return (void *)data;
4676 void *R_FrameData_Store(size_t size, void *data)
4678 void *d = R_FrameData_Alloc(size);
4680 memcpy(d, data, size);
4684 void R_FrameData_SetMark(void)
4686 if (!r_framedata_mem)
4688 r_framedata_mem->mark = r_framedata_mem->current;
4691 void R_FrameData_ReturnToMark(void)
4693 if (!r_framedata_mem)
4695 r_framedata_mem->current = r_framedata_mem->mark;
4698 //==================================================================================
4700 // avoid reusing the same buffer objects on consecutive frames
4701 #define R_BUFFERDATA_CYCLE 3
4703 typedef struct r_bufferdata_buffer_s
4705 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4706 size_t size; // how much usable space
4707 size_t current; // how much space in use
4708 r_meshbuffer_t *buffer; // the buffer itself
4710 r_bufferdata_buffer_t;
4712 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4713 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4715 /// frees all dynamic buffers
4716 void R_BufferData_Reset(void)
4719 r_bufferdata_buffer_t **p, *mem;
4720 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4722 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4725 p = &r_bufferdata_buffer[cycle][type];
4731 R_Mesh_DestroyMeshBuffer(mem->buffer);
4738 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4739 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4741 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4743 float newvalue = r_buffermegs[type].value;
4745 // increase the cvar if we have to (but only if we already have a mem)
4746 if (mustgrow && mem)
4748 newvalue = bound(0.25f, newvalue, 256.0f);
4749 while (newvalue * 1024*1024 < minsize)
4752 // clamp the cvar to valid range
4753 newvalue = bound(0.25f, newvalue, 256.0f);
4754 if (r_buffermegs[type].value != newvalue)
4755 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4757 // calculate size in bytes
4758 size = (size_t)(newvalue * 1024*1024);
4759 size = bound(131072, size, 256*1024*1024);
4761 // allocate a new buffer if the size is different (purge old one later)
4762 // or if we were told we must grow the buffer
4763 if (!mem || mem->size != size || mustgrow)
4765 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4768 if (type == R_BUFFERDATA_VERTEX)
4769 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4770 else if (type == R_BUFFERDATA_INDEX16)
4771 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4772 else if (type == R_BUFFERDATA_INDEX32)
4773 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4774 else if (type == R_BUFFERDATA_UNIFORM)
4775 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4776 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4777 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4781 void R_BufferData_NewFrame(void)
4784 r_bufferdata_buffer_t **p, *mem;
4785 // cycle to the next frame's buffers
4786 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4787 // if we ran out of space on the last time we used these buffers, free the old memory now
4788 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4790 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4792 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4793 // free all but the head buffer, this is how we recycle obsolete
4794 // buffers after they are no longer in use
4795 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4801 R_Mesh_DestroyMeshBuffer(mem->buffer);
4804 // reset the current offset
4805 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4810 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4812 r_bufferdata_buffer_t *mem;
4816 *returnbufferoffset = 0;
4818 // align size to a byte boundary appropriate for the buffer type, this
4819 // makes all allocations have aligned start offsets
4820 if (type == R_BUFFERDATA_UNIFORM)
4821 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4823 padsize = (datasize + 15) & ~15;
4825 // if we ran out of space in this buffer we must allocate a new one
4826 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4827 R_BufferData_Resize(type, true, padsize);
4829 // if the resize did not give us enough memory, fail
4830 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4831 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4833 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4834 offset = mem->current;
4835 mem->current += padsize;
4837 // upload the data to the buffer at the chosen offset
4839 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4840 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4842 // count the usage for stats
4843 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4844 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4846 // return the buffer offset
4847 *returnbufferoffset = offset;
4852 //==================================================================================
4854 // LordHavoc: animcache originally written by Echon, rewritten since then
4857 * Animation cache prevents re-generating mesh data for an animated model
4858 * multiple times in one frame for lighting, shadowing, reflections, etc.
4861 void R_AnimCache_Free(void)
4865 void R_AnimCache_ClearCache(void)
4868 entity_render_t *ent;
4870 for (i = 0;i < r_refdef.scene.numentities;i++)
4872 ent = r_refdef.scene.entities[i];
4873 ent->animcache_vertex3f = NULL;
4874 ent->animcache_vertex3f_vertexbuffer = NULL;
4875 ent->animcache_vertex3f_bufferoffset = 0;
4876 ent->animcache_normal3f = NULL;
4877 ent->animcache_normal3f_vertexbuffer = NULL;
4878 ent->animcache_normal3f_bufferoffset = 0;
4879 ent->animcache_svector3f = NULL;
4880 ent->animcache_svector3f_vertexbuffer = NULL;
4881 ent->animcache_svector3f_bufferoffset = 0;
4882 ent->animcache_tvector3f = NULL;
4883 ent->animcache_tvector3f_vertexbuffer = NULL;
4884 ent->animcache_tvector3f_bufferoffset = 0;
4885 ent->animcache_vertexmesh = NULL;
4886 ent->animcache_vertexmesh_vertexbuffer = NULL;
4887 ent->animcache_vertexmesh_bufferoffset = 0;
4888 ent->animcache_skeletaltransform3x4 = NULL;
4889 ent->animcache_skeletaltransform3x4buffer = NULL;
4890 ent->animcache_skeletaltransform3x4offset = 0;
4891 ent->animcache_skeletaltransform3x4size = 0;
4895 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4899 // check if we need the meshbuffers
4900 if (!vid.useinterleavedarrays)
4903 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4904 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4905 // TODO: upload vertexbuffer?
4906 if (ent->animcache_vertexmesh)
4908 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4909 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4910 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4911 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4912 for (i = 0;i < numvertices;i++)
4913 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4914 if (ent->animcache_svector3f)
4915 for (i = 0;i < numvertices;i++)
4916 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4917 if (ent->animcache_tvector3f)
4918 for (i = 0;i < numvertices;i++)
4919 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4920 if (ent->animcache_normal3f)
4921 for (i = 0;i < numvertices;i++)
4922 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4926 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4928 dp_model_t *model = ent->model;
4931 // see if this ent is worth caching
4932 if (!model || !model->Draw || !model->AnimateVertices)
4934 // nothing to cache if it contains no animations and has no skeleton
4935 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4937 // see if it is already cached for gpuskeletal
4938 if (ent->animcache_skeletaltransform3x4)
4940 // see if it is already cached as a mesh
4941 if (ent->animcache_vertex3f)
4943 // check if we need to add normals or tangents
4944 if (ent->animcache_normal3f)
4945 wantnormals = false;
4946 if (ent->animcache_svector3f)
4947 wanttangents = false;
4948 if (!wantnormals && !wanttangents)
4952 // check which kind of cache we need to generate
4953 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4955 // cache the skeleton so the vertex shader can use it
4956 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4957 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4958 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4959 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4960 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4961 // note: this can fail if the buffer is at the grow limit
4962 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4963 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4965 else if (ent->animcache_vertex3f)
4967 // mesh was already cached but we may need to add normals/tangents
4968 // (this only happens with multiple views, reflections, cameras, etc)
4969 if (wantnormals || wanttangents)
4971 numvertices = model->surfmesh.num_vertices;
4973 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4976 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4977 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4979 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4980 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4981 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4982 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4983 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4988 // generate mesh cache
4989 numvertices = model->surfmesh.num_vertices;
4990 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4992 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4995 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4996 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4998 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4999 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5000 if (wantnormals || wanttangents)
5002 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5003 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5004 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5006 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5007 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5008 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5013 void R_AnimCache_CacheVisibleEntities(void)
5016 qboolean wantnormals = true;
5017 qboolean wanttangents = !r_showsurfaces.integer;
5019 switch(vid.renderpath)
5021 case RENDERPATH_GL20:
5022 case RENDERPATH_D3D9:
5023 case RENDERPATH_D3D10:
5024 case RENDERPATH_D3D11:
5025 case RENDERPATH_GLES2:
5027 case RENDERPATH_GL11:
5028 case RENDERPATH_GL13:
5029 case RENDERPATH_GLES1:
5030 wanttangents = false;
5032 case RENDERPATH_SOFT:
5036 if (r_shownormals.integer)
5037 wanttangents = wantnormals = true;
5039 // TODO: thread this
5040 // NOTE: R_PrepareRTLights() also caches entities
5042 for (i = 0;i < r_refdef.scene.numentities;i++)
5043 if (r_refdef.viewcache.entityvisible[i])
5044 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5047 //==================================================================================
5049 extern cvar_t r_overheadsprites_pushback;
5051 static void R_View_UpdateEntityLighting (void)
5054 entity_render_t *ent;
5055 vec3_t tempdiffusenormal, avg;
5056 vec_t f, fa, fd, fdd;
5057 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5059 for (i = 0;i < r_refdef.scene.numentities;i++)
5061 ent = r_refdef.scene.entities[i];
5063 // skip unseen models
5064 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5068 if (ent->model && ent->model == cl.worldmodel)
5070 // TODO: use modellight for r_ambient settings on world?
5071 VectorSet(ent->modellight_ambient, 0, 0, 0);
5072 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5073 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5077 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5079 // aleady updated by CSQC
5080 // TODO: force modellight on BSP models in this case?
5081 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5085 // fetch the lighting from the worldmodel data
5086 VectorClear(ent->modellight_ambient);
5087 VectorClear(ent->modellight_diffuse);
5088 VectorClear(tempdiffusenormal);
5089 if (ent->flags & RENDER_LIGHT)
5092 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5094 // complete lightning for lit sprites
5095 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5096 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5098 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5099 org[2] = org[2] + r_overheadsprites_pushback.value;
5100 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5103 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5105 if(ent->flags & RENDER_EQUALIZE)
5107 // first fix up ambient lighting...
5108 if(r_equalize_entities_minambient.value > 0)
5110 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5113 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5114 if(fa < r_equalize_entities_minambient.value * fd)
5117 // fa'/fd' = minambient
5118 // fa'+0.25*fd' = fa+0.25*fd
5120 // fa' = fd' * minambient
5121 // fd'*(0.25+minambient) = fa+0.25*fd
5123 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5124 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5126 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5127 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
5128 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5129 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5134 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5136 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5137 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5141 // adjust brightness and saturation to target
5142 avg[0] = avg[1] = avg[2] = fa / f;
5143 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5144 avg[0] = avg[1] = avg[2] = fd / f;
5145 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5151 VectorSet(ent->modellight_ambient, 1, 1, 1);
5154 // move the light direction into modelspace coordinates for lighting code
5155 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5156 if(VectorLength2(ent->modellight_lightdir) == 0)
5157 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5158 VectorNormalize(ent->modellight_lightdir);
5162 #define MAX_LINEOFSIGHTTRACES 64
5164 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5167 vec3_t boxmins, boxmaxs;
5170 dp_model_t *model = r_refdef.scene.worldmodel;
5172 if (!model || !model->brush.TraceLineOfSight)
5175 // expand the box a little
5176 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5177 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5178 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5179 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5180 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5181 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5183 // return true if eye is inside enlarged box
5184 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5188 VectorCopy(eye, start);
5189 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5190 if (model->brush.TraceLineOfSight(model, start, end))
5193 // try various random positions
5194 for (i = 0;i < numsamples;i++)
5196 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5197 if (model->brush.TraceLineOfSight(model, start, end))
5205 static void R_View_UpdateEntityVisible (void)
5210 entity_render_t *ent;
5212 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5213 : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5214 : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL
5215 : RENDER_EXTERIORMODEL;
5216 if (!r_drawviewmodel.integer)
5217 renderimask |= RENDER_VIEWMODEL;
5218 if (!r_drawexteriormodel.integer)
5219 renderimask |= RENDER_EXTERIORMODEL;
5220 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5222 // worldmodel can check visibility
5223 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5224 for (i = 0;i < r_refdef.scene.numentities;i++)
5226 ent = r_refdef.scene.entities[i];
5227 if (!(ent->flags & renderimask))
5228 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
5229 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
5230 r_refdef.viewcache.entityvisible[i] = true;
5235 // no worldmodel or it can't check visibility
5236 for (i = 0;i < r_refdef.scene.numentities;i++)
5238 ent = r_refdef.scene.entities[i];
5239 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
5242 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5243 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5245 for (i = 0;i < r_refdef.scene.numentities;i++)
5247 if (!r_refdef.viewcache.entityvisible[i])
5249 ent = r_refdef.scene.entities[i];
5250 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5252 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5254 continue; // temp entities do pvs only
5255 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5256 ent->last_trace_visibility = realtime;
5257 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5258 r_refdef.viewcache.entityvisible[i] = 0;
5264 /// only used if skyrendermasked, and normally returns false
5265 static int R_DrawBrushModelsSky (void)
5268 entity_render_t *ent;
5271 for (i = 0;i < r_refdef.scene.numentities;i++)
5273 if (!r_refdef.viewcache.entityvisible[i])
5275 ent = r_refdef.scene.entities[i];
5276 if (!ent->model || !ent->model->DrawSky)
5278 ent->model->DrawSky(ent);
5284 static void R_DrawNoModel(entity_render_t *ent);
5285 static void R_DrawModels(void)
5288 entity_render_t *ent;
5290 for (i = 0;i < r_refdef.scene.numentities;i++)
5292 if (!r_refdef.viewcache.entityvisible[i])
5294 ent = r_refdef.scene.entities[i];
5295 r_refdef.stats[r_stat_entities]++;
5297 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5300 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5301 Con_Printf("R_DrawModels\n");
5302 Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
5303 Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
5304 Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
5307 if (ent->model && ent->model->Draw != NULL)
5308 ent->model->Draw(ent);
5314 static void R_DrawModelsDepth(void)
5317 entity_render_t *ent;
5319 for (i = 0;i < r_refdef.scene.numentities;i++)
5321 if (!r_refdef.viewcache.entityvisible[i])
5323 ent = r_refdef.scene.entities[i];
5324 if (ent->model && ent->model->DrawDepth != NULL)
5325 ent->model->DrawDepth(ent);
5329 static void R_DrawModelsDebug(void)
5332 entity_render_t *ent;
5334 for (i = 0;i < r_refdef.scene.numentities;i++)
5336 if (!r_refdef.viewcache.entityvisible[i])
5338 ent = r_refdef.scene.entities[i];
5339 if (ent->model && ent->model->DrawDebug != NULL)
5340 ent->model->DrawDebug(ent);
5344 static void R_DrawModelsAddWaterPlanes(void)
5347 entity_render_t *ent;
5349 for (i = 0;i < r_refdef.scene.numentities;i++)
5351 if (!r_refdef.viewcache.entityvisible[i])
5353 ent = r_refdef.scene.entities[i];
5354 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5355 ent->model->DrawAddWaterPlanes(ent);
5359 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5361 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5363 if (r_hdr_irisadaptation.integer)
5368 vec3_t diffusenormal;
5370 vec_t brightness = 0.0f;
5375 VectorCopy(r_refdef.view.forward, forward);
5376 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5378 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5379 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5380 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5381 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5382 d = DotProduct(forward, diffusenormal);
5383 brightness += VectorLength(ambient);
5385 brightness += d * VectorLength(diffuse);
5387 brightness *= 1.0f / c;
5388 brightness += 0.00001f; // make sure it's never zero
5389 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5390 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5391 current = r_hdr_irisadaptation_value.value;
5393 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5394 else if (current > goal)
5395 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5396 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5397 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5399 else if (r_hdr_irisadaptation_value.value != 1.0f)
5400 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5403 static void R_View_SetFrustum(const int *scissor)
5406 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5407 vec3_t forward, left, up, origin, v;
5411 // flipped x coordinates (because x points left here)
5412 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5413 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5415 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5416 switch(vid.renderpath)
5418 case RENDERPATH_D3D9:
5419 case RENDERPATH_D3D10:
5420 case RENDERPATH_D3D11:
5421 // non-flipped y coordinates
5422 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5423 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5425 case RENDERPATH_SOFT:
5426 case RENDERPATH_GL11:
5427 case RENDERPATH_GL13:
5428 case RENDERPATH_GL20:
5429 case RENDERPATH_GLES1:
5430 case RENDERPATH_GLES2:
5431 // non-flipped y coordinates
5432 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5433 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5438 // we can't trust r_refdef.view.forward and friends in reflected scenes
5439 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5442 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5443 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5444 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5445 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5446 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5447 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5448 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5449 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5450 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5451 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5452 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5453 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5457 zNear = r_refdef.nearclip;
5458 nudge = 1.0 - 1.0 / (1<<23);
5459 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5460 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5461 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5462 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5463 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5464 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5465 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5466 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5472 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5473 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5474 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5475 r_refdef.view.frustum[0].dist = m[15] - m[12];
5477 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5478 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5479 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5480 r_refdef.view.frustum[1].dist = m[15] + m[12];
5482 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5483 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5484 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5485 r_refdef.view.frustum[2].dist = m[15] - m[13];
5487 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5488 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5489 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5490 r_refdef.view.frustum[3].dist = m[15] + m[13];
5492 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5493 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5494 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5495 r_refdef.view.frustum[4].dist = m[15] - m[14];
5497 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5498 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5499 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5500 r_refdef.view.frustum[5].dist = m[15] + m[14];
5503 if (r_refdef.view.useperspective)
5505 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5506 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5507 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5508 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5509 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5511 // then the normals from the corners relative to origin
5512 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5513 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5514 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5515 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5517 // in a NORMAL view, forward cross left == up
5518 // in a REFLECTED view, forward cross left == down
5519 // so our cross products above need to be adjusted for a left handed coordinate system
5520 CrossProduct(forward, left, v);
5521 if(DotProduct(v, up) < 0)
5523 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5524 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5525 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5526 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5529 // Leaving those out was a mistake, those were in the old code, and they
5530 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5531 // I couldn't reproduce it after adding those normalizations. --blub
5532 VectorNormalize(r_refdef.view.frustum[0].normal);
5533 VectorNormalize(r_refdef.view.frustum[1].normal);
5534 VectorNormalize(r_refdef.view.frustum[2].normal);
5535 VectorNormalize(r_refdef.view.frustum[3].normal);
5537 // make the corners absolute
5538 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5539 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5540 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5541 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5544 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5546 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5547 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5548 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5549 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5550 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5554 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5555 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5556 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5557 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5558 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5559 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5560 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5561 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5562 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5563 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5565 r_refdef.view.numfrustumplanes = 5;
5567 if (r_refdef.view.useclipplane)
5569 r_refdef.view.numfrustumplanes = 6;
5570 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5573 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5574 PlaneClassify(r_refdef.view.frustum + i);
5576 // LordHavoc: note to all quake engine coders, Quake had a special case
5577 // for 90 degrees which assumed a square view (wrong), so I removed it,
5578 // Quake2 has it disabled as well.
5580 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5581 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5582 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5583 //PlaneClassify(&frustum[0]);
5585 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5586 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5587 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5588 //PlaneClassify(&frustum[1]);
5590 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5591 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5592 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5593 //PlaneClassify(&frustum[2]);
5595 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5596 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5597 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5598 //PlaneClassify(&frustum[3]);
5601 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5602 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5603 //PlaneClassify(&frustum[4]);
5606 static void R_View_UpdateWithScissor(const int *myscissor)
5608 R_Main_ResizeViewCache();
5609 R_View_SetFrustum(myscissor);
5610 R_View_WorldVisibility(r_refdef.view.useclipplane);
5611 R_View_UpdateEntityVisible();
5612 R_View_UpdateEntityLighting();
5615 static void R_View_Update(void)
5617 R_Main_ResizeViewCache();
5618 R_View_SetFrustum(NULL);
5619 R_View_WorldVisibility(r_refdef.view.useclipplane);
5620 R_View_UpdateEntityVisible();
5621 R_View_UpdateEntityLighting();
5624 float viewscalefpsadjusted = 1.0f;
5626 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5628 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5629 scale = bound(0.03125f, scale, 1.0f);
5630 *outwidth = (int)ceil(width * scale);
5631 *outheight = (int)ceil(height * scale);
5634 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5636 const float *customclipplane = NULL;
5638 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5639 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5641 // LordHavoc: couldn't figure out how to make this approach the
5642 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5643 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5644 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5645 dist = r_refdef.view.clipplane.dist;
5646 plane[0] = r_refdef.view.clipplane.normal[0];
5647 plane[1] = r_refdef.view.clipplane.normal[1];
5648 plane[2] = r_refdef.view.clipplane.normal[2];
5650 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5653 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5654 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5656 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5657 if (!r_refdef.view.useperspective)
5658 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5659 else if (vid.stencil && r_useinfinitefarclip.integer)
5660 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5662 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5663 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5664 R_SetViewport(&r_refdef.view.viewport);
5665 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5667 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5668 float screenplane[4];
5669 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5670 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5671 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5672 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5673 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5677 void R_EntityMatrix(const matrix4x4_t *matrix)
5679 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5681 gl_modelmatrixchanged = false;
5682 gl_modelmatrix = *matrix;
5683 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5684 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5685 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5686 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5688 switch(vid.renderpath)
5690 case RENDERPATH_D3D9:
5692 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5693 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5696 case RENDERPATH_D3D10:
5697 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5699 case RENDERPATH_D3D11:
5700 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5702 case RENDERPATH_GL11:
5703 case RENDERPATH_GL13:
5704 case RENDERPATH_GLES1:
5706 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5709 case RENDERPATH_SOFT:
5710 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5711 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5713 case RENDERPATH_GL20:
5714 case RENDERPATH_GLES2:
5715 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5716 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5722 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5724 r_viewport_t viewport;
5728 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5729 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
5730 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5731 R_SetViewport(&viewport);
5732 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5733 GL_Color(1, 1, 1, 1);
5734 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5735 GL_BlendFunc(GL_ONE, GL_ZERO);
5736 GL_ScissorTest(false);
5737 GL_DepthMask(false);
5738 GL_DepthRange(0, 1);
5739 GL_DepthTest(false);
5740 GL_DepthFunc(GL_LEQUAL);
5741 R_EntityMatrix(&identitymatrix);
5742 R_Mesh_ResetTextureState();
5743 GL_PolygonOffset(0, 0);
5744 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5745 switch(vid.renderpath)
5747 case RENDERPATH_GL11:
5748 case RENDERPATH_GL13:
5749 case RENDERPATH_GL20:
5750 case RENDERPATH_GLES1:
5751 case RENDERPATH_GLES2:
5752 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5754 case RENDERPATH_D3D9:
5755 case RENDERPATH_D3D10:
5756 case RENDERPATH_D3D11:
5757 case RENDERPATH_SOFT:
5760 GL_CullFace(GL_NONE);
5765 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5769 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5772 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5776 R_SetupView(true, fbo, depthtexture, colortexture);
5777 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5778 GL_Color(1, 1, 1, 1);
5779 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5780 GL_BlendFunc(GL_ONE, GL_ZERO);
5781 GL_ScissorTest(true);
5783 GL_DepthRange(0, 1);
5785 GL_DepthFunc(GL_LEQUAL);
5786 R_EntityMatrix(&identitymatrix);
5787 R_Mesh_ResetTextureState();
5788 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5789 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5790 switch(vid.renderpath)
5792 case RENDERPATH_GL11:
5793 case RENDERPATH_GL13:
5794 case RENDERPATH_GL20:
5795 case RENDERPATH_GLES1:
5796 case RENDERPATH_GLES2:
5797 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5799 case RENDERPATH_D3D9:
5800 case RENDERPATH_D3D10:
5801 case RENDERPATH_D3D11:
5802 case RENDERPATH_SOFT:
5805 GL_CullFace(r_refdef.view.cullface_back);
5810 R_RenderView_UpdateViewVectors
5813 void R_RenderView_UpdateViewVectors(void)
5815 // break apart the view matrix into vectors for various purposes
5816 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5817 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5818 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5819 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5820 // make an inverted copy of the view matrix for tracking sprites
5821 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5824 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5825 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5827 static void R_Water_StartFrame(void)
5830 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5831 r_waterstate_waterplane_t *p;
5832 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5834 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5837 switch(vid.renderpath)
5839 case RENDERPATH_GL20:
5840 case RENDERPATH_D3D9:
5841 case RENDERPATH_D3D10:
5842 case RENDERPATH_D3D11:
5843 case RENDERPATH_SOFT:
5844 case RENDERPATH_GLES2:
5846 case RENDERPATH_GL11:
5847 case RENDERPATH_GL13:
5848 case RENDERPATH_GLES1:
5852 // set waterwidth and waterheight to the water resolution that will be
5853 // used (often less than the screen resolution for faster rendering)
5854 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5856 // calculate desired texture sizes
5857 // can't use water if the card does not support the texture size
5858 if (!r_water.integer || r_showsurfaces.integer)
5859 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5860 else if (vid.support.arb_texture_non_power_of_two)
5862 texturewidth = waterwidth;
5863 textureheight = waterheight;
5864 camerawidth = waterwidth;
5865 cameraheight = waterheight;
5869 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5870 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5871 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5872 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5875 // allocate textures as needed
5876 if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5878 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5879 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5881 if (p->texture_refraction)
5882 R_FreeTexture(p->texture_refraction);
5883 p->texture_refraction = NULL;
5884 if (p->fbo_refraction)
5885 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5886 p->fbo_refraction = 0;
5887 if (p->texture_reflection)
5888 R_FreeTexture(p->texture_reflection);
5889 p->texture_reflection = NULL;
5890 if (p->fbo_reflection)
5891 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5892 p->fbo_reflection = 0;
5893 if (p->texture_camera)
5894 R_FreeTexture(p->texture_camera);
5895 p->texture_camera = NULL;
5897 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5900 memset(&r_fb.water, 0, sizeof(r_fb.water));
5901 r_fb.water.texturewidth = texturewidth;
5902 r_fb.water.textureheight = textureheight;
5903 r_fb.water.camerawidth = camerawidth;
5904 r_fb.water.cameraheight = cameraheight;
5907 if (r_fb.water.texturewidth)
5909 int scaledwidth, scaledheight;
5911 r_fb.water.enabled = true;
5913 // water resolution is usually reduced
5914 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5915 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5916 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5918 // set up variables that will be used in shader setup
5919 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5920 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5921 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5922 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5925 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5926 r_fb.water.numwaterplanes = 0;
5929 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5931 int planeindex, bestplaneindex, vertexindex;
5932 vec3_t mins, maxs, normal, center, v, n;
5933 vec_t planescore, bestplanescore;
5935 r_waterstate_waterplane_t *p;
5936 texture_t *t = R_GetCurrentTexture(surface->texture);
5938 rsurface.texture = t;
5939 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5940 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5941 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5943 // average the vertex normals, find the surface bounds (after deformvertexes)
5944 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5945 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5946 VectorCopy(n, normal);
5947 VectorCopy(v, mins);
5948 VectorCopy(v, maxs);
5949 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5951 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5952 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5953 VectorAdd(normal, n, normal);
5954 mins[0] = min(mins[0], v[0]);
5955 mins[1] = min(mins[1], v[1]);
5956 mins[2] = min(mins[2], v[2]);
5957 maxs[0] = max(maxs[0], v[0]);
5958 maxs[1] = max(maxs[1], v[1]);
5959 maxs[2] = max(maxs[2], v[2]);
5961 VectorNormalize(normal);
5962 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5964 VectorCopy(normal, plane.normal);
5965 VectorNormalize(plane.normal);
5966 plane.dist = DotProduct(center, plane.normal);
5967 PlaneClassify(&plane);
5968 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5970 // skip backfaces (except if nocullface is set)
5971 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5973 VectorNegate(plane.normal, plane.normal);
5975 PlaneClassify(&plane);
5979 // find a matching plane if there is one
5980 bestplaneindex = -1;
5981 bestplanescore = 1048576.0f;
5982 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5984 if(p->camera_entity == t->camera_entity)
5986 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5987 if (bestplaneindex < 0 || bestplanescore > planescore)
5989 bestplaneindex = planeindex;
5990 bestplanescore = planescore;
5994 planeindex = bestplaneindex;
5995 p = r_fb.water.waterplanes + planeindex;
5997 // if this surface does not fit any known plane rendered this frame, add one
5998 if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6000 // store the new plane
6001 planeindex = r_fb.water.numwaterplanes++;
6002 p = r_fb.water.waterplanes + planeindex;
6004 // clear materialflags and pvs
6005 p->materialflags = 0;
6006 p->pvsvalid = false;
6007 p->camera_entity = t->camera_entity;
6008 VectorCopy(mins, p->mins);
6009 VectorCopy(maxs, p->maxs);
6013 // merge mins/maxs when we're adding this surface to the plane
6014 p->mins[0] = min(p->mins[0], mins[0]);
6015 p->mins[1] = min(p->mins[1], mins[1]);
6016 p->mins[2] = min(p->mins[2], mins[2]);
6017 p->maxs[0] = max(p->maxs[0], maxs[0]);
6018 p->maxs[1] = max(p->maxs[1], maxs[1]);
6019 p->maxs[2] = max(p->maxs[2], maxs[2]);
6021 // merge this surface's materialflags into the waterplane
6022 p->materialflags |= t->currentmaterialflags;
6023 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6025 // merge this surface's PVS into the waterplane
6026 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6027 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6029 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6035 extern cvar_t r_drawparticles;
6036 extern cvar_t r_drawdecals;
6038 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6041 r_refdef_view_t originalview;
6042 r_refdef_view_t myview;
6043 int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
6044 r_waterstate_waterplane_t *p;
6046 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6049 originalview = r_refdef.view;
6051 // lowquality hack, temporarily shut down some cvars and restore afterwards
6052 qualityreduction = r_water_lowquality.integer;
6053 if (qualityreduction > 0)
6055 if (qualityreduction >= 1)
6057 old_r_shadows = r_shadows.integer;
6058 old_r_worldrtlight = r_shadow_realtime_world.integer;
6059 old_r_dlight = r_shadow_realtime_dlight.integer;
6060 Cvar_SetValueQuick(&r_shadows, 0);
6061 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6062 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6064 if (qualityreduction >= 2)
6066 old_r_dynamic = r_dynamic.integer;
6067 old_r_particles = r_drawparticles.integer;
6068 old_r_decals = r_drawdecals.integer;
6069 Cvar_SetValueQuick(&r_dynamic, 0);
6070 Cvar_SetValueQuick(&r_drawparticles, 0);
6071 Cvar_SetValueQuick(&r_drawdecals, 0);
6075 // make sure enough textures are allocated
6076 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6078 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6080 if (!p->texture_refraction)
6081 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6082 if (!p->texture_refraction)
6086 if (r_fb.water.depthtexture == NULL)
6087 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6088 if (p->fbo_refraction == 0)
6089 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6092 else if (p->materialflags & MATERIALFLAG_CAMERA)
6094 if (!p->texture_camera)
6095 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
6096 if (!p->texture_camera)
6100 if (r_fb.water.depthtexture == NULL)
6101 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6102 if (p->fbo_camera == 0)
6103 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6107 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6109 if (!p->texture_reflection)
6110 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6111 if (!p->texture_reflection)
6115 if (r_fb.water.depthtexture == NULL)
6116 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6117 if (p->fbo_reflection == 0)
6118 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6124 r_refdef.view = originalview;
6125 r_refdef.view.showdebug = false;
6126 r_refdef.view.width = r_fb.water.waterwidth;
6127 r_refdef.view.height = r_fb.water.waterheight;
6128 r_refdef.view.useclipplane = true;
6129 myview = r_refdef.view;
6130 r_fb.water.renderingscene = true;
6131 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6133 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6135 r_refdef.view = myview;
6136 if(r_water_scissormode.integer)
6138 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6139 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6140 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6143 // render reflected scene and copy into texture
6144 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6145 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6146 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6147 r_refdef.view.clipplane = p->plane;
6148 // reverse the cullface settings for this render
6149 r_refdef.view.cullface_front = GL_FRONT;
6150 r_refdef.view.cullface_back = GL_BACK;
6151 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6153 r_refdef.view.usecustompvs = true;
6155 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6157 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6160 r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
6161 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6162 R_ClearScreen(r_refdef.fogenabled);
6163 if(r_water_scissormode.integer & 2)
6164 R_View_UpdateWithScissor(myscissor);
6167 R_AnimCache_CacheVisibleEntities();
6168 if(r_water_scissormode.integer & 1)
6169 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6170 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6172 if (!p->fbo_reflection)
6173 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6174 r_fb.water.hideplayer = false;
6177 // render the normal view scene and copy into texture
6178 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
6179 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6181 r_refdef.view = myview;
6182 if(r_water_scissormode.integer)
6184 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6185 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6186 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6189 r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6191 r_refdef.view.clipplane = p->plane;
6192 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6193 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6195 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6197 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6198 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6199 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6200 R_RenderView_UpdateViewVectors();
6201 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6203 r_refdef.view.usecustompvs = true;
6204 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
6208 PlaneClassify(&r_refdef.view.clipplane);
6210 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6211 R_ClearScreen(r_refdef.fogenabled);
6212 if(r_water_scissormode.integer & 2)
6213 R_View_UpdateWithScissor(myscissor);
6216 R_AnimCache_CacheVisibleEntities();
6217 if(r_water_scissormode.integer & 1)
6218 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6219 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6221 if (!p->fbo_refraction)
6222 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6223 r_fb.water.hideplayer = false;
6225 else if (p->materialflags & MATERIALFLAG_CAMERA)
6227 r_refdef.view = myview;
6229 r_refdef.view.clipplane = p->plane;
6230 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6231 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6233 r_refdef.view.width = r_fb.water.camerawidth;
6234 r_refdef.view.height = r_fb.water.cameraheight;
6235 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6236 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6237 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6238 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6240 if(p->camera_entity)
6242 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6243 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6246 // note: all of the view is used for displaying... so
6247 // there is no use in scissoring
6249 // reverse the cullface settings for this render
6250 r_refdef.view.cullface_front = GL_FRONT;
6251 r_refdef.view.cullface_back = GL_BACK;
6252 // also reverse the view matrix
6253 Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
6254 R_RenderView_UpdateViewVectors();
6255 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6257 r_refdef.view.usecustompvs = true;
6258 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
6261 // camera needs no clipplane
6262 r_refdef.view.useclipplane = false;
6264 PlaneClassify(&r_refdef.view.clipplane);
6266 r_fb.water.hideplayer = false;
6268 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6269 R_ClearScreen(r_refdef.fogenabled);
6271 R_AnimCache_CacheVisibleEntities();
6272 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6275 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6276 r_fb.water.hideplayer = false;
6280 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6281 r_fb.water.renderingscene = false;
6282 r_refdef.view = originalview;
6283 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6284 if (!r_fb.water.depthtexture)
6285 R_ClearScreen(r_refdef.fogenabled);
6287 R_AnimCache_CacheVisibleEntities();
6290 r_refdef.view = originalview;
6291 r_fb.water.renderingscene = false;
6292 Cvar_SetValueQuick(&r_water, 0);
6293 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6295 // lowquality hack, restore cvars
6296 if (qualityreduction > 0)
6298 if (qualityreduction >= 1)
6300 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6301 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6302 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6304 if (qualityreduction >= 2)
6306 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6307 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6308 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6313 static void R_Bloom_StartFrame(void)
6316 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6317 int viewwidth, viewheight;
6318 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6319 textype_t textype = TEXTYPE_COLORBUFFER;
6321 switch (vid.renderpath)
6323 case RENDERPATH_GL20:
6324 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6325 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6327 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6328 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6331 case RENDERPATH_GL11:
6332 case RENDERPATH_GL13:
6333 case RENDERPATH_GLES1:
6334 case RENDERPATH_GLES2:
6335 case RENDERPATH_D3D9:
6336 case RENDERPATH_D3D10:
6337 case RENDERPATH_D3D11:
6338 r_fb.usedepthtextures = false;
6340 case RENDERPATH_SOFT:
6341 r_fb.usedepthtextures = true;
6345 if (r_viewscale_fpsscaling.integer)
6347 double actualframetime;
6348 double targetframetime;
6350 actualframetime = r_refdef.lastdrawscreentime;
6351 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6352 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6353 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6354 if (r_viewscale_fpsscaling_stepsize.value > 0)
6355 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6356 viewscalefpsadjusted += adjust;
6357 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6360 viewscalefpsadjusted = 1.0f;
6362 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6364 switch(vid.renderpath)
6366 case RENDERPATH_GL20:
6367 case RENDERPATH_D3D9:
6368 case RENDERPATH_D3D10:
6369 case RENDERPATH_D3D11:
6370 case RENDERPATH_SOFT:
6371 case RENDERPATH_GLES2:
6373 case RENDERPATH_GL11:
6374 case RENDERPATH_GL13:
6375 case RENDERPATH_GLES1:
6379 // set bloomwidth and bloomheight to the bloom resolution that will be
6380 // used (often less than the screen resolution for faster rendering)
6381 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6382 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6383 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6384 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6385 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6387 // calculate desired texture sizes
6388 if (vid.support.arb_texture_non_power_of_two)
6390 screentexturewidth = vid.width;
6391 screentextureheight = vid.height;
6392 bloomtexturewidth = r_fb.bloomwidth;
6393 bloomtextureheight = r_fb.bloomheight;
6397 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6398 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6399 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6400 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6403 if ((r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
6405 Cvar_SetValueQuick(&r_bloom, 0);
6406 Cvar_SetValueQuick(&r_motionblur, 0);
6407 Cvar_SetValueQuick(&r_damageblur, 0);
6410 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6412 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6414 && r_viewscale.value == 1.0f
6415 && !r_viewscale_fpsscaling.integer)
6416 screentexturewidth = screentextureheight = 0;
6417 if (!r_bloom.integer)
6418 bloomtexturewidth = bloomtextureheight = 0;
6420 // allocate textures as needed
6421 if (r_fb.screentexturewidth != screentexturewidth
6422 || r_fb.screentextureheight != screentextureheight
6423 || r_fb.bloomtexturewidth != bloomtexturewidth
6424 || r_fb.bloomtextureheight != bloomtextureheight
6425 || r_fb.textype != textype
6426 || useviewfbo != (r_fb.fbo != 0))
6428 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6430 if (r_fb.bloomtexture[i])
6431 R_FreeTexture(r_fb.bloomtexture[i]);
6432 r_fb.bloomtexture[i] = NULL;
6434 if (r_fb.bloomfbo[i])
6435 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6436 r_fb.bloomfbo[i] = 0;
6440 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6443 if (r_fb.colortexture)
6444 R_FreeTexture(r_fb.colortexture);
6445 r_fb.colortexture = NULL;
6447 if (r_fb.depthtexture)
6448 R_FreeTexture(r_fb.depthtexture);
6449 r_fb.depthtexture = NULL;
6451 if (r_fb.ghosttexture)
6452 R_FreeTexture(r_fb.ghosttexture);
6453 r_fb.ghosttexture = NULL;
6455 r_fb.screentexturewidth = screentexturewidth;
6456 r_fb.screentextureheight = screentextureheight;
6457 r_fb.bloomtexturewidth = bloomtexturewidth;
6458 r_fb.bloomtextureheight = bloomtextureheight;
6459 r_fb.textype = textype;
6461 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6463 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6464 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6465 r_fb.ghosttexture_valid = false;
6466 r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6469 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6470 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6471 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6475 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6477 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6479 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6481 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6486 // bloom texture is a different resolution
6487 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6488 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6489 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6490 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6491 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6493 // set up a texcoord array for the full resolution screen image
6494 // (we have to keep this around to copy back during final render)
6495 r_fb.screentexcoord2f[0] = 0;
6496 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6497 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6498 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6499 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6500 r_fb.screentexcoord2f[5] = 0;
6501 r_fb.screentexcoord2f[6] = 0;
6502 r_fb.screentexcoord2f[7] = 0;
6506 for (i = 1;i < 8;i += 2)
6508 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6512 // set up a texcoord array for the reduced resolution bloom image
6513 // (which will be additive blended over the screen image)
6514 r_fb.bloomtexcoord2f[0] = 0;
6515 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6516 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6517 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6518 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6519 r_fb.bloomtexcoord2f[5] = 0;
6520 r_fb.bloomtexcoord2f[6] = 0;
6521 r_fb.bloomtexcoord2f[7] = 0;
6523 switch(vid.renderpath)
6525 case RENDERPATH_GL11:
6526 case RENDERPATH_GL13:
6527 case RENDERPATH_GL20:
6528 case RENDERPATH_SOFT:
6529 case RENDERPATH_GLES1:
6530 case RENDERPATH_GLES2:
6532 case RENDERPATH_D3D9:
6533 case RENDERPATH_D3D10:
6534 case RENDERPATH_D3D11:
6535 for (i = 0;i < 4;i++)
6537 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6538 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6539 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6540 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6545 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6548 r_refdef.view.clear = true;
6551 static void R_Bloom_MakeTexture(void)
6554 float xoffset, yoffset, r, brighten;
6556 float colorscale = r_bloom_colorscale.value;
6558 r_refdef.stats[r_stat_bloom]++;
6561 // this copy is unnecessary since it happens in R_BlendView already
6564 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6565 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6569 // scale down screen texture to the bloom texture size
6571 r_fb.bloomindex = 0;
6572 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6573 R_SetViewport(&r_fb.bloomviewport);
6574 GL_DepthTest(false);
6575 GL_BlendFunc(GL_ONE, GL_ZERO);
6576 GL_Color(colorscale, colorscale, colorscale, 1);
6577 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6578 switch(vid.renderpath)
6580 case RENDERPATH_GL11:
6581 case RENDERPATH_GL13:
6582 case RENDERPATH_GL20:
6583 case RENDERPATH_GLES1:
6584 case RENDERPATH_GLES2:
6585 case RENDERPATH_SOFT:
6586 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6588 case RENDERPATH_D3D9:
6589 case RENDERPATH_D3D10:
6590 case RENDERPATH_D3D11:
6591 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6594 // TODO: do boxfilter scale-down in shader?
6595 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6596 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6597 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6599 // we now have a properly scaled bloom image
6600 if (!r_fb.bloomfbo[r_fb.bloomindex])
6602 // copy it into the bloom texture
6603 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6604 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6607 // multiply bloom image by itself as many times as desired
6608 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6610 intex = r_fb.bloomtexture[r_fb.bloomindex];
6611 r_fb.bloomindex ^= 1;
6612 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6614 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6615 if (!r_fb.bloomfbo[r_fb.bloomindex])
6617 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6618 GL_Color(r,r,r,1); // apply fix factor
6623 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6624 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6625 GL_Color(1,1,1,1); // no fix factor supported here
6627 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6628 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6629 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6630 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6632 if (!r_fb.bloomfbo[r_fb.bloomindex])
6634 // copy the darkened image to a texture
6635 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6636 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6640 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6641 brighten = r_bloom_brighten.value;
6642 brighten = sqrt(brighten);
6644 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6646 for (dir = 0;dir < 2;dir++)
6648 intex = r_fb.bloomtexture[r_fb.bloomindex];
6649 r_fb.bloomindex ^= 1;
6650 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6651 // blend on at multiple vertical offsets to achieve a vertical blur
6652 // TODO: do offset blends using GLSL
6653 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6654 GL_BlendFunc(GL_ONE, GL_ZERO);
6655 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6656 for (x = -range;x <= range;x++)
6658 if (!dir){xoffset = 0;yoffset = x;}
6659 else {xoffset = x;yoffset = 0;}
6660 xoffset /= (float)r_fb.bloomtexturewidth;
6661 yoffset /= (float)r_fb.bloomtextureheight;
6662 // compute a texcoord array with the specified x and y offset
6663 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6664 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6665 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6666 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6667 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6668 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6669 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6670 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6671 // this r value looks like a 'dot' particle, fading sharply to
6672 // black at the edges
6673 // (probably not realistic but looks good enough)
6674 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6675 //r = brighten/(range*2+1);
6676 r = brighten / (range * 2 + 1);
6678 r *= (1 - x*x/(float)(range*range));
6679 GL_Color(r, r, r, 1);
6680 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6681 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6682 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6683 GL_BlendFunc(GL_ONE, GL_ONE);
6686 if (!r_fb.bloomfbo[r_fb.bloomindex])
6688 // copy the vertically or horizontally blurred bloom view to a texture
6689 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6690 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6695 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6697 unsigned int permutation;
6698 float uservecs[4][4];
6700 R_EntityMatrix(&identitymatrix);
6702 switch (vid.renderpath)
6704 case RENDERPATH_GL20:
6705 case RENDERPATH_D3D9:
6706 case RENDERPATH_D3D10:
6707 case RENDERPATH_D3D11:
6708 case RENDERPATH_SOFT:
6709 case RENDERPATH_GLES2:
6711 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6712 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6713 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6714 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6715 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6717 if (r_fb.colortexture)
6721 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6722 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6725 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6727 // declare variables
6728 float blur_factor, blur_mouseaccel, blur_velocity;
6729 static float blur_average;
6730 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6732 // set a goal for the factoring
6733 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6734 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6735 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6736 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6737 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6738 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6740 // from the goal, pick an averaged value between goal and last value
6741 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6742 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6744 // enforce minimum amount of blur
6745 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6747 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6749 // calculate values into a standard alpha
6750 cl.motionbluralpha = 1 - exp(-
6752 (r_motionblur.value * blur_factor / 80)
6754 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6757 max(0.0001, cl.time - cl.oldtime) // fps independent
6760 // randomization for the blur value to combat persistent ghosting
6761 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6762 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6765 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6766 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6768 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6769 GL_Color(1, 1, 1, cl.motionbluralpha);
6770 switch(vid.renderpath)
6772 case RENDERPATH_GL11:
6773 case RENDERPATH_GL13:
6774 case RENDERPATH_GL20:
6775 case RENDERPATH_GLES1:
6776 case RENDERPATH_GLES2:
6777 case RENDERPATH_SOFT:
6778 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6780 case RENDERPATH_D3D9:
6781 case RENDERPATH_D3D10:
6782 case RENDERPATH_D3D11:
6783 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6786 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6787 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6788 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6791 // updates old view angles for next pass
6792 VectorCopy(cl.viewangles, blur_oldangles);
6794 // copy view into the ghost texture
6795 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6796 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6797 r_fb.ghosttexture_valid = true;
6802 // no r_fb.colortexture means we're rendering to the real fb
6803 // we may still have to do view tint...
6804 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6806 // apply a color tint to the whole view
6807 R_ResetViewRendering2D(0, NULL, NULL);
6808 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6809 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6810 R_SetupShader_Generic_NoTexture(false, true);
6811 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6812 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6814 break; // no screen processing, no bloom, skip it
6817 if (r_fb.bloomtexture[0])
6819 // make the bloom texture
6820 R_Bloom_MakeTexture();
6823 #if _MSC_VER >= 1400
6824 #define sscanf sscanf_s
6826 memset(uservecs, 0, sizeof(uservecs));
6827 if (r_glsl_postprocess_uservec1_enable.integer)
6828 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6829 if (r_glsl_postprocess_uservec2_enable.integer)
6830 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6831 if (r_glsl_postprocess_uservec3_enable.integer)
6832 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6833 if (r_glsl_postprocess_uservec4_enable.integer)
6834 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6836 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6837 GL_Color(1, 1, 1, 1);
6838 GL_BlendFunc(GL_ONE, GL_ZERO);
6840 switch(vid.renderpath)
6842 case RENDERPATH_GL20:
6843 case RENDERPATH_GLES2:
6844 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6845 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6846 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6847 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6848 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6849 if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6850 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6851 if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6852 if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6853 if (r_glsl_permutation->loc_UserVec3 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6854 if (r_glsl_permutation->loc_UserVec4 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6855 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6856 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6857 if (r_glsl_permutation->loc_BloomColorSubtract >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6859 case RENDERPATH_D3D9:
6861 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6862 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6863 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6864 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6865 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6866 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6867 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6868 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6869 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6870 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6871 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6872 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6873 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6874 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6875 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6878 case RENDERPATH_D3D10:
6879 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6881 case RENDERPATH_D3D11:
6882 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6884 case RENDERPATH_SOFT:
6885 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6886 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6887 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6888 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6889 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6890 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6891 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6892 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6893 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6894 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6895 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6896 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6897 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6898 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6903 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6904 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6906 case RENDERPATH_GL11:
6907 case RENDERPATH_GL13:
6908 case RENDERPATH_GLES1:
6909 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6911 // apply a color tint to the whole view
6912 R_ResetViewRendering2D(0, NULL, NULL);
6913 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6914 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6915 R_SetupShader_Generic_NoTexture(false, true);
6916 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6917 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6923 matrix4x4_t r_waterscrollmatrix;
6925 void R_UpdateFog(void)
6928 if (gamemode == GAME_NEHAHRA)
6930 if (gl_fogenable.integer)
6932 r_refdef.oldgl_fogenable = true;
6933 r_refdef.fog_density = gl_fogdensity.value;
6934 r_refdef.fog_red = gl_fogred.value;
6935 r_refdef.fog_green = gl_foggreen.value;
6936 r_refdef.fog_blue = gl_fogblue.value;
6937 r_refdef.fog_alpha = 1;
6938 r_refdef.fog_start = 0;
6939 r_refdef.fog_end = gl_skyclip.value;
6940 r_refdef.fog_height = 1<<30;
6941 r_refdef.fog_fadedepth = 128;
6943 else if (r_refdef.oldgl_fogenable)
6945 r_refdef.oldgl_fogenable = false;
6946 r_refdef.fog_density = 0;
6947 r_refdef.fog_red = 0;
6948 r_refdef.fog_green = 0;
6949 r_refdef.fog_blue = 0;
6950 r_refdef.fog_alpha = 0;
6951 r_refdef.fog_start = 0;
6952 r_refdef.fog_end = 0;
6953 r_refdef.fog_height = 1<<30;
6954 r_refdef.fog_fadedepth = 128;
6959 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6960 r_refdef.fog_start = max(0, r_refdef.fog_start);
6961 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6963 if (r_refdef.fog_density && r_drawfog.integer)
6965 r_refdef.fogenabled = true;
6966 // this is the point where the fog reaches 0.9986 alpha, which we
6967 // consider a good enough cutoff point for the texture
6968 // (0.9986 * 256 == 255.6)
6969 if (r_fog_exp2.integer)
6970 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6972 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6973 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6974 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6975 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6976 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6977 R_BuildFogHeightTexture();
6978 // fog color was already set
6979 // update the fog texture
6980 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
6981 R_BuildFogTexture();
6982 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6983 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6986 r_refdef.fogenabled = false;
6989 if (r_refdef.fog_density)
6991 r_refdef.fogcolor[0] = r_refdef.fog_red;
6992 r_refdef.fogcolor[1] = r_refdef.fog_green;
6993 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6995 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6996 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6997 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6998 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7002 VectorCopy(r_refdef.fogcolor, fogvec);
7003 // color.rgb *= ContrastBoost * SceneBrightness;
7004 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7005 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7006 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7007 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7012 void R_UpdateVariables(void)
7016 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7018 r_refdef.farclip = r_farclip_base.value;
7019 if (r_refdef.scene.worldmodel)
7020 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7021 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7023 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7024 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7025 r_refdef.polygonfactor = 0;
7026 r_refdef.polygonoffset = 0;
7027 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7028 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7030 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7031 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7032 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7033 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7034 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7035 if (FAKELIGHT_ENABLED)
7037 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7039 else if (r_refdef.scene.worldmodel)
7041 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7043 if (r_showsurfaces.integer)
7045 r_refdef.scene.rtworld = false;
7046 r_refdef.scene.rtworldshadows = false;
7047 r_refdef.scene.rtdlight = false;
7048 r_refdef.scene.rtdlightshadows = false;
7049 r_refdef.lightmapintensity = 0;
7052 r_gpuskeletal = false;
7053 switch(vid.renderpath)
7055 case RENDERPATH_GL20:
7056 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7057 case RENDERPATH_D3D9:
7058 case RENDERPATH_D3D10:
7059 case RENDERPATH_D3D11:
7060 case RENDERPATH_SOFT:
7061 case RENDERPATH_GLES2:
7062 if(v_glslgamma.integer && !vid_gammatables_trivial)
7064 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7066 // build GLSL gamma texture
7067 #define RAMPWIDTH 256
7068 unsigned short ramp[RAMPWIDTH * 3];
7069 unsigned char rampbgr[RAMPWIDTH][4];
7072 r_texture_gammaramps_serial = vid_gammatables_serial;
7074 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7075 for(i = 0; i < RAMPWIDTH; ++i)
7077 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7078 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7079 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7082 if (r_texture_gammaramps)
7084 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7088 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7094 // remove GLSL gamma texture
7097 case RENDERPATH_GL11:
7098 case RENDERPATH_GL13:
7099 case RENDERPATH_GLES1:
7104 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7105 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7111 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7112 if( scenetype != r_currentscenetype ) {
7113 // store the old scenetype
7114 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7115 r_currentscenetype = scenetype;
7116 // move in the new scene
7117 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7126 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7128 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7129 if( scenetype == r_currentscenetype ) {
7130 return &r_refdef.scene;
7132 return &r_scenes_store[ scenetype ];
7136 static int R_SortEntities_Compare(const void *ap, const void *bp)
7138 const entity_render_t *a = *(const entity_render_t **)ap;
7139 const entity_render_t *b = *(const entity_render_t **)bp;
7142 if(a->model < b->model)
7144 if(a->model > b->model)
7148 // TODO possibly calculate the REAL skinnum here first using
7150 if(a->skinnum < b->skinnum)
7152 if(a->skinnum > b->skinnum)
7155 // everything we compared is equal
7158 static void R_SortEntities(void)
7160 // below or equal 2 ents, sorting never gains anything
7161 if(r_refdef.scene.numentities <= 2)
7164 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7172 int dpsoftrast_test;
7173 extern cvar_t r_shadow_bouncegrid;
7174 void R_RenderView(void)
7176 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7178 rtexture_t *depthtexture;
7179 rtexture_t *colortexture;
7181 dpsoftrast_test = r_test.integer;
7183 if (r_timereport_active)
7184 R_TimeReport("start");
7185 r_textureframe++; // used only by R_GetCurrentTexture
7186 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7188 if(R_CompileShader_CheckStaticParms())
7191 if (!r_drawentities.integer)
7192 r_refdef.scene.numentities = 0;
7193 else if (r_sortentities.integer)
7196 R_AnimCache_ClearCache();
7198 /* adjust for stereo display */
7199 if(R_Stereo_Active())
7201 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
7202 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7205 if (r_refdef.view.isoverlay)
7207 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7208 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7209 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7210 R_TimeReport("depthclear");
7212 r_refdef.view.showdebug = false;
7214 r_fb.water.enabled = false;
7215 r_fb.water.numwaterplanes = 0;
7217 R_RenderScene(0, NULL, NULL);
7219 r_refdef.view.matrix = originalmatrix;
7225 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7227 r_refdef.view.matrix = originalmatrix;
7231 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7233 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7234 // in sRGB fallback, behave similar to true sRGB: convert this
7235 // value from linear to sRGB
7236 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7238 R_RenderView_UpdateViewVectors();
7240 R_Shadow_UpdateWorldLightSelection();
7242 R_Bloom_StartFrame();
7244 // apply bloom brightness offset
7245 if(r_fb.bloomtexture[0])
7246 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7248 R_Water_StartFrame();
7250 // now we probably have an fbo to render into
7252 depthtexture = r_fb.depthtexture;
7253 colortexture = r_fb.colortexture;
7256 if (r_timereport_active)
7257 R_TimeReport("viewsetup");
7259 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7261 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7263 R_ClearScreen(r_refdef.fogenabled);
7264 if (r_timereport_active)
7265 R_TimeReport("viewclear");
7267 r_refdef.view.clear = true;
7269 r_refdef.view.showdebug = true;
7272 if (r_timereport_active)
7273 R_TimeReport("visibility");
7275 R_AnimCache_CacheVisibleEntities();
7276 if (r_timereport_active)
7277 R_TimeReport("animcache");
7279 R_Shadow_UpdateBounceGridTexture();
7280 if (r_timereport_active && r_shadow_bouncegrid.integer)
7281 R_TimeReport("bouncegrid");
7283 r_fb.water.numwaterplanes = 0;
7284 if (r_fb.water.enabled)
7285 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7287 R_RenderScene(fbo, depthtexture, colortexture);
7288 r_fb.water.numwaterplanes = 0;
7290 R_BlendView(fbo, depthtexture, colortexture);
7291 if (r_timereport_active)
7292 R_TimeReport("blendview");
7294 GL_Scissor(0, 0, vid.width, vid.height);
7295 GL_ScissorTest(false);
7297 r_refdef.view.matrix = originalmatrix;
7302 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7304 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7306 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7307 if (r_timereport_active)
7308 R_TimeReport("waterworld");
7311 // don't let sound skip if going slow
7312 if (r_refdef.scene.extraupdate)
7315 R_DrawModelsAddWaterPlanes();
7316 if (r_timereport_active)
7317 R_TimeReport("watermodels");
7319 if (r_fb.water.numwaterplanes)
7321 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7322 if (r_timereport_active)
7323 R_TimeReport("waterscenes");
7327 extern cvar_t cl_locs_show;
7328 static void R_DrawLocs(void);
7329 static void R_DrawEntityBBoxes(void);
7330 static void R_DrawModelDecals(void);
7331 extern cvar_t cl_decals_newsystem;
7332 extern qboolean r_shadow_usingdeferredprepass;
7333 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7335 qboolean shadowmapping = false;
7337 if (r_timereport_active)
7338 R_TimeReport("beginscene");
7340 r_refdef.stats[r_stat_renders]++;
7344 // don't let sound skip if going slow
7345 if (r_refdef.scene.extraupdate)
7348 R_MeshQueue_BeginScene();
7352 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
7354 if (r_timereport_active)
7355 R_TimeReport("skystartframe");
7357 if (cl.csqc_vidvars.drawworld)
7359 // don't let sound skip if going slow
7360 if (r_refdef.scene.extraupdate)
7363 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7365 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7366 if (r_timereport_active)
7367 R_TimeReport("worldsky");
7370 if (R_DrawBrushModelsSky() && r_timereport_active)
7371 R_TimeReport("bmodelsky");
7373 if (skyrendermasked && skyrenderlater)
7375 // we have to force off the water clipping plane while rendering sky
7376 R_SetupView(false, fbo, depthtexture, colortexture);
7378 R_SetupView(true, fbo, depthtexture, colortexture);
7379 if (r_timereport_active)
7380 R_TimeReport("sky");
7384 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7385 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7386 R_Shadow_PrepareModelShadows();
7387 if (r_timereport_active)
7388 R_TimeReport("preparelights");
7390 if (R_Shadow_ShadowMappingEnabled())
7391 shadowmapping = true;
7393 if (r_shadow_usingdeferredprepass)
7394 R_Shadow_DrawPrepass();
7396 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7398 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7399 if (r_timereport_active)
7400 R_TimeReport("worlddepth");
7402 if (r_depthfirst.integer >= 2)
7404 R_DrawModelsDepth();
7405 if (r_timereport_active)
7406 R_TimeReport("modeldepth");
7409 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7411 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7412 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7413 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7414 // don't let sound skip if going slow
7415 if (r_refdef.scene.extraupdate)
7419 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7421 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7422 if (r_timereport_active)
7423 R_TimeReport("world");
7426 // don't let sound skip if going slow
7427 if (r_refdef.scene.extraupdate)
7431 if (r_timereport_active)
7432 R_TimeReport("models");
7434 // don't let sound skip if going slow
7435 if (r_refdef.scene.extraupdate)
7438 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7440 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7441 R_DrawModelShadows(fbo, depthtexture, colortexture);
7442 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7443 // don't let sound skip if going slow
7444 if (r_refdef.scene.extraupdate)
7448 if (!r_shadow_usingdeferredprepass)
7450 R_Shadow_DrawLights();
7451 if (r_timereport_active)
7452 R_TimeReport("rtlights");
7455 // don't let sound skip if going slow
7456 if (r_refdef.scene.extraupdate)
7459 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7461 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7462 R_DrawModelShadows(fbo, depthtexture, colortexture);
7463 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7464 // don't let sound skip if going slow
7465 if (r_refdef.scene.extraupdate)
7469 if (cl.csqc_vidvars.drawworld)
7471 if (cl_decals_newsystem.integer)
7473 R_DrawModelDecals();
7474 if (r_timereport_active)
7475 R_TimeReport("modeldecals");
7480 if (r_timereport_active)
7481 R_TimeReport("decals");
7485 if (r_timereport_active)
7486 R_TimeReport("particles");
7489 if (r_timereport_active)
7490 R_TimeReport("explosions");
7492 R_DrawLightningBeams();
7493 if (r_timereport_active)
7494 R_TimeReport("lightning");
7498 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7500 if (r_refdef.view.showdebug)
7502 if (cl_locs_show.integer)
7505 if (r_timereport_active)
7506 R_TimeReport("showlocs");
7509 if (r_drawportals.integer)
7512 if (r_timereport_active)
7513 R_TimeReport("portals");
7516 if (r_showbboxes.value > 0)
7518 R_DrawEntityBBoxes();
7519 if (r_timereport_active)
7520 R_TimeReport("bboxes");
7524 if (r_transparent.integer)
7526 R_MeshQueue_RenderTransparent();
7527 if (r_timereport_active)
7528 R_TimeReport("drawtrans");
7531 if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0 || r_showoverdraw.value > 0))
7533 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7534 if (r_timereport_active)
7535 R_TimeReport("worlddebug");
7536 R_DrawModelsDebug();
7537 if (r_timereport_active)
7538 R_TimeReport("modeldebug");
7541 if (cl.csqc_vidvars.drawworld)
7543 R_Shadow_DrawCoronas();
7544 if (r_timereport_active)
7545 R_TimeReport("coronas");
7550 GL_DepthTest(false);
7551 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7552 GL_Color(1, 1, 1, 1);
7553 qglBegin(GL_POLYGON);
7554 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7555 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7556 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7557 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7559 qglBegin(GL_POLYGON);
7560 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
7561 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
7562 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
7563 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
7565 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7569 // don't let sound skip if going slow
7570 if (r_refdef.scene.extraupdate)
7574 static const unsigned short bboxelements[36] =
7584 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7587 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7589 RSurf_ActiveWorldEntity();
7591 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7592 GL_DepthMask(false);
7593 GL_DepthRange(0, 1);
7594 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7595 // R_Mesh_ResetTextureState();
7597 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7598 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7599 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7600 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7601 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7602 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7603 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7604 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7605 R_FillColors(color4f, 8, cr, cg, cb, ca);
7606 if (r_refdef.fogenabled)
7608 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7610 f1 = RSurf_FogVertex(v);
7612 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7613 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7614 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7617 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7618 R_Mesh_ResetTextureState();
7619 R_SetupShader_Generic_NoTexture(false, false);
7620 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7623 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7625 prvm_prog_t *prog = SVVM_prog;
7628 prvm_edict_t *edict;
7630 // this function draws bounding boxes of server entities
7634 GL_CullFace(GL_NONE);
7635 R_SetupShader_Generic_NoTexture(false, false);
7637 for (i = 0;i < numsurfaces;i++)
7639 edict = PRVM_EDICT_NUM(surfacelist[i]);
7640 switch ((int)PRVM_serveredictfloat(edict, solid))
7642 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7643 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7644 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7645 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7646 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7647 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7648 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7650 color[3] *= r_showbboxes.value;
7651 color[3] = bound(0, color[3], 1);
7652 GL_DepthTest(!r_showdisabledepthtest.integer);
7653 GL_CullFace(r_refdef.view.cullface_front);
7654 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7658 static void R_DrawEntityBBoxes(void)
7661 prvm_edict_t *edict;
7663 prvm_prog_t *prog = SVVM_prog;
7665 // this function draws bounding boxes of server entities
7669 for (i = 0;i < prog->num_edicts;i++)
7671 edict = PRVM_EDICT_NUM(i);
7672 if (edict->priv.server->free)
7674 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7675 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7677 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7679 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7680 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7684 static const int nomodelelement3i[24] =
7696 static const unsigned short nomodelelement3s[24] =
7708 static const float nomodelvertex3f[6*3] =
7718 static const float nomodelcolor4f[6*4] =
7720 0.0f, 0.0f, 0.5f, 1.0f,
7721 0.0f, 0.0f, 0.5f, 1.0f,
7722 0.0f, 0.5f, 0.0f, 1.0f,
7723 0.0f, 0.5f, 0.0f, 1.0f,
7724 0.5f, 0.0f, 0.0f, 1.0f,
7725 0.5f, 0.0f, 0.0f, 1.0f
7728 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7734 RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7736 // this is only called once per entity so numsurfaces is always 1, and
7737 // surfacelist is always {0}, so this code does not handle batches
7739 if (rsurface.ent_flags & RENDER_ADDITIVE)
7741 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7742 GL_DepthMask(false);
7744 else if (rsurface.colormod[3] < 1)
7746 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7747 GL_DepthMask(false);
7751 GL_BlendFunc(GL_ONE, GL_ZERO);
7754 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7755 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7756 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7757 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7758 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7759 for (i = 0, c = color4f;i < 6;i++, c += 4)
7761 c[0] *= rsurface.colormod[0];
7762 c[1] *= rsurface.colormod[1];
7763 c[2] *= rsurface.colormod[2];
7764 c[3] *= rsurface.colormod[3];
7766 if (r_refdef.fogenabled)
7768 for (i = 0, c = color4f;i < 6;i++, c += 4)
7770 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7772 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7773 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7774 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7777 // R_Mesh_ResetTextureState();
7778 R_SetupShader_Generic_NoTexture(false, false);
7779 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7780 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7783 void R_DrawNoModel(entity_render_t *ent)
7786 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7787 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7788 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7790 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7793 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7795 vec3_t right1, right2, diff, normal;
7797 VectorSubtract (org2, org1, normal);
7799 // calculate 'right' vector for start
7800 VectorSubtract (r_refdef.view.origin, org1, diff);
7801 CrossProduct (normal, diff, right1);
7802 VectorNormalize (right1);
7804 // calculate 'right' vector for end
7805 VectorSubtract (r_refdef.view.origin, org2, diff);
7806 CrossProduct (normal, diff, right2);
7807 VectorNormalize (right2);
7809 vert[ 0] = org1[0] + width * right1[0];
7810 vert[ 1] = org1[1] + width * right1[1];
7811 vert[ 2] = org1[2] + width * right1[2];
7812 vert[ 3] = org1[0] - width * right1[0];
7813 vert[ 4] = org1[1] - width * right1[1];
7814 vert[ 5] = org1[2] - width * right1[2];
7815 vert[ 6] = org2[0] - width * right2[0];
7816 vert[ 7] = org2[1] - width * right2[1];
7817 vert[ 8] = org2[2] - width * right2[2];
7818 vert[ 9] = org2[0] + width * right2[0];
7819 vert[10] = org2[1] + width * right2[1];
7820 vert[11] = org2[2] + width * right2[2];
7823 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
7825 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7826 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7827 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7828 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7829 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7830 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7831 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7832 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7833 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7834 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7835 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7836 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7839 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7844 VectorSet(v, x, y, z);
7845 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7846 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7848 if (i == mesh->numvertices)
7850 if (mesh->numvertices < mesh->maxvertices)
7852 VectorCopy(v, vertex3f);
7853 mesh->numvertices++;
7855 return mesh->numvertices;
7861 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7865 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7866 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7867 e = mesh->element3i + mesh->numtriangles * 3;
7868 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7870 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7871 if (mesh->numtriangles < mesh->maxtriangles)
7876 mesh->numtriangles++;
7878 element[1] = element[2];
7882 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7886 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7887 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7888 e = mesh->element3i + mesh->numtriangles * 3;
7889 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7891 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7892 if (mesh->numtriangles < mesh->maxtriangles)
7897 mesh->numtriangles++;
7899 element[1] = element[2];
7903 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7904 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7906 int planenum, planenum2;
7909 mplane_t *plane, *plane2;
7911 double temppoints[2][256*3];
7912 // figure out how large a bounding box we need to properly compute this brush
7914 for (w = 0;w < numplanes;w++)
7915 maxdist = max(maxdist, fabs(planes[w].dist));
7916 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7917 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7918 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7922 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7923 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7925 if (planenum2 == planenum)
7927 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
7930 if (tempnumpoints < 3)
7932 // generate elements forming a triangle fan for this polygon
7933 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7937 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7939 texturelayer_t *layer;
7940 layer = t->currentlayers + t->currentnumlayers++;
7942 layer->depthmask = depthmask;
7943 layer->blendfunc1 = blendfunc1;
7944 layer->blendfunc2 = blendfunc2;
7945 layer->texture = texture;
7946 layer->texmatrix = *matrix;
7947 layer->color[0] = r;
7948 layer->color[1] = g;
7949 layer->color[2] = b;
7950 layer->color[3] = a;
7953 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7955 if(parms[0] == 0 && parms[1] == 0)
7957 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7958 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7963 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7966 index = parms[2] + rsurface.shadertime * parms[3];
7967 index -= floor(index);
7968 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7971 case Q3WAVEFUNC_NONE:
7972 case Q3WAVEFUNC_NOISE:
7973 case Q3WAVEFUNC_COUNT:
7976 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7977 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7978 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7979 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7980 case Q3WAVEFUNC_TRIANGLE:
7982 f = index - floor(index);
7995 f = parms[0] + parms[1] * f;
7996 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7997 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8001 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8007 matrix4x4_t matrix, temp;
8008 switch(tcmod->tcmod)
8012 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8013 matrix = r_waterscrollmatrix;
8015 matrix = identitymatrix;
8017 case Q3TCMOD_ENTITYTRANSLATE:
8018 // this is used in Q3 to allow the gamecode to control texcoord
8019 // scrolling on the entity, which is not supported in darkplaces yet.
8020 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8022 case Q3TCMOD_ROTATE:
8023 f = tcmod->parms[0] * rsurface.shadertime;
8024 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8025 Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
8026 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8029 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8031 case Q3TCMOD_SCROLL:
8032 // extra care is needed because of precision breakdown with large values of time
8033 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8034 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8035 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8037 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8038 w = (int) tcmod->parms[0];
8039 h = (int) tcmod->parms[1];
8040 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8042 idx = (int) floor(f * w * h);
8043 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8045 case Q3TCMOD_STRETCH:
8046 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8047 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8049 case Q3TCMOD_TRANSFORM:
8050 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8051 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8052 VectorSet(tcmat + 6, 0 , 0 , 1);
8053 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8054 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8056 case Q3TCMOD_TURBULENT:
8057 // this is handled in the RSurf_PrepareVertices function
8058 matrix = identitymatrix;
8062 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8065 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8067 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8068 char name[MAX_QPATH];
8069 skinframe_t *skinframe;
8070 unsigned char pixels[296*194];
8071 strlcpy(cache->name, skinname, sizeof(cache->name));
8072 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8073 if (developer_loading.integer)
8074 Con_Printf("loading %s\n", name);
8075 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8076 if (!skinframe || !skinframe->base)
8079 fs_offset_t filesize;
8081 f = FS_LoadFile(name, tempmempool, true, &filesize);
8084 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8085 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8089 cache->skinframe = skinframe;
8092 texture_t *R_GetCurrentTexture(texture_t *t)
8095 const entity_render_t *ent = rsurface.entity;
8096 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8097 q3shaderinfo_layer_tcmod_t *tcmod;
8099 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8100 return t->currentframe;
8101 t->update_lastrenderframe = r_textureframe;
8102 t->update_lastrenderentity = (void *)ent;
8104 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8105 t->camera_entity = ent->entitynumber;
8107 t->camera_entity = 0;
8109 // switch to an alternate material if this is a q1bsp animated material
8111 texture_t *texture = t;
8112 int s = rsurface.ent_skinnum;
8113 if ((unsigned int)s >= (unsigned int)model->numskins)
8115 if (model->skinscenes)
8117 if (model->skinscenes[s].framecount > 1)
8118 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8120 s = model->skinscenes[s].firstframe;
8123 t = t + s * model->num_surfaces;
8126 // use an alternate animation if the entity's frame is not 0,
8127 // and only if the texture has an alternate animation
8128 if (rsurface.ent_alttextures && t->anim_total[1])
8129 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8131 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8133 texture->currentframe = t;
8136 // update currentskinframe to be a qw skin or animation frame
8137 if (rsurface.ent_qwskin >= 0)
8139 i = rsurface.ent_qwskin;
8140 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8142 r_qwskincache_size = cl.maxclients;
8144 Mem_Free(r_qwskincache);
8145 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8147 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8148 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8149 t->currentskinframe = r_qwskincache[i].skinframe;
8150 if (t->currentskinframe == NULL)
8151 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8153 else if (t->numskinframes >= 2)
8154 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8155 if (t->backgroundnumskinframes >= 2)
8156 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8158 t->currentmaterialflags = t->basematerialflags;
8159 t->currentalpha = rsurface.colormod[3];
8160 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8161 t->currentalpha *= r_wateralpha.value;
8162 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8163 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8164 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8165 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8166 if (!(rsurface.ent_flags & RENDER_LIGHT))
8167 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8168 else if (FAKELIGHT_ENABLED)
8170 // no modellight if using fakelight for the map
8172 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8174 // pick a model lighting mode
8175 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8176 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8178 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8180 if (rsurface.ent_flags & RENDER_ADDITIVE)
8181 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8182 else if (t->currentalpha < 1)
8183 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8184 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8185 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8186 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8187 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8188 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8189 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8190 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8191 if (t->backgroundnumskinframes)
8192 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8193 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8195 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8196 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8199 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8200 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8202 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8203 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8205 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8206 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8208 // there is no tcmod
8209 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8211 t->currenttexmatrix = r_waterscrollmatrix;
8212 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8214 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8216 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8217 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8220 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8221 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8222 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8223 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8225 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8226 if (t->currentskinframe->qpixels)
8227 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8228 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8229 if (!t->basetexture)
8230 t->basetexture = r_texture_notexture;
8231 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8232 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8233 t->nmaptexture = t->currentskinframe->nmap;
8234 if (!t->nmaptexture)
8235 t->nmaptexture = r_texture_blanknormalmap;
8236 t->glosstexture = r_texture_black;
8237 t->glowtexture = t->currentskinframe->glow;
8238 t->fogtexture = t->currentskinframe->fog;
8239 t->reflectmasktexture = t->currentskinframe->reflect;
8240 if (t->backgroundnumskinframes)
8242 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8243 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8244 t->backgroundglosstexture = r_texture_black;
8245 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8246 if (!t->backgroundnmaptexture)
8247 t->backgroundnmaptexture = r_texture_blanknormalmap;
8248 // make sure that if glow is going to be used, both textures are not NULL
8249 if (!t->backgroundglowtexture && t->glowtexture)
8250 t->backgroundglowtexture = r_texture_black;
8251 if (!t->glowtexture && t->backgroundglowtexture)
8252 t->glowtexture = r_texture_black;
8256 t->backgroundbasetexture = r_texture_white;
8257 t->backgroundnmaptexture = r_texture_blanknormalmap;
8258 t->backgroundglosstexture = r_texture_black;
8259 t->backgroundglowtexture = NULL;
8261 t->specularpower = r_shadow_glossexponent.value;
8262 // TODO: store reference values for these in the texture?
8263 t->specularscale = 0;
8264 if (r_shadow_gloss.integer > 0)
8266 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8268 if (r_shadow_glossintensity.value > 0)
8270 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8271 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8272 t->specularscale = r_shadow_glossintensity.value;
8275 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8277 t->glosstexture = r_texture_white;
8278 t->backgroundglosstexture = r_texture_white;
8279 t->specularscale = r_shadow_gloss2intensity.value;
8280 t->specularpower = r_shadow_gloss2exponent.value;
8283 t->specularscale *= t->specularscalemod;
8284 t->specularpower *= t->specularpowermod;
8285 t->rtlightambient = 0;
8287 // lightmaps mode looks bad with dlights using actual texturing, so turn
8288 // off the colormap and glossmap, but leave the normalmap on as it still
8289 // accurately represents the shading involved
8290 if (gl_lightmaps.integer)
8292 t->basetexture = r_texture_grey128;
8293 t->pantstexture = r_texture_black;
8294 t->shirttexture = r_texture_black;
8295 if (gl_lightmaps.integer < 2)
8296 t->nmaptexture = r_texture_blanknormalmap;
8297 t->glosstexture = r_texture_black;
8298 t->glowtexture = NULL;
8299 t->fogtexture = NULL;
8300 t->reflectmasktexture = NULL;
8301 t->backgroundbasetexture = NULL;
8302 if (gl_lightmaps.integer < 2)
8303 t->backgroundnmaptexture = r_texture_blanknormalmap;
8304 t->backgroundglosstexture = r_texture_black;
8305 t->backgroundglowtexture = NULL;
8306 t->specularscale = 0;
8307 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8310 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8311 VectorClear(t->dlightcolor);
8312 t->currentnumlayers = 0;
8313 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8315 int blendfunc1, blendfunc2;
8317 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8319 blendfunc1 = GL_SRC_ALPHA;
8320 blendfunc2 = GL_ONE;
8322 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8324 blendfunc1 = GL_SRC_ALPHA;
8325 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8327 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8329 blendfunc1 = t->customblendfunc[0];
8330 blendfunc2 = t->customblendfunc[1];
8334 blendfunc1 = GL_ONE;
8335 blendfunc2 = GL_ZERO;
8337 // don't colormod evilblend textures
8338 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8339 VectorSet(t->lightmapcolor, 1, 1, 1);
8340 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8341 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8343 // fullbright is not affected by r_refdef.lightmapintensity
8344 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]);
8345 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8346 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]);
8347 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8348 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]);
8352 vec3_t ambientcolor;
8354 // set the color tint used for lights affecting this surface
8355 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8357 // q3bsp has no lightmap updates, so the lightstylevalue that
8358 // would normally be baked into the lightmap must be
8359 // applied to the color
8360 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8361 if (model->type == mod_brushq3)
8362 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8363 colorscale *= r_refdef.lightmapintensity;
8364 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8365 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8366 // basic lit geometry
8367 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]);
8368 // add pants/shirt if needed
8369 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8370 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]);
8371 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8372 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]);
8373 // now add ambient passes if needed
8374 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8376 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]);
8377 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8378 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8379 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8380 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8383 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8384 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]);
8385 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8387 // if this is opaque use alpha blend which will darken the earlier
8390 // if this is an alpha blended material, all the earlier passes
8391 // were darkened by fog already, so we only need to add the fog
8392 // color ontop through the fog mask texture
8394 // if this is an additive blended material, all the earlier passes
8395 // were darkened by fog already, and we should not add fog color
8396 // (because the background was not darkened, there is no fog color
8397 // that was lost behind it).
8398 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]);
8402 return t->currentframe;
8405 rsurfacestate_t rsurface;
8407 void RSurf_ActiveWorldEntity(void)
8409 dp_model_t *model = r_refdef.scene.worldmodel;
8410 //if (rsurface.entity == r_refdef.scene.worldentity)
8412 rsurface.entity = r_refdef.scene.worldentity;
8413 rsurface.skeleton = NULL;
8414 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8415 rsurface.ent_skinnum = 0;
8416 rsurface.ent_qwskin = -1;
8417 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8418 rsurface.shadertime = r_refdef.scene.time;
8419 rsurface.matrix = identitymatrix;
8420 rsurface.inversematrix = identitymatrix;
8421 rsurface.matrixscale = 1;
8422 rsurface.inversematrixscale = 1;
8423 R_EntityMatrix(&identitymatrix);
8424 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8425 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8426 rsurface.fograngerecip = r_refdef.fograngerecip;
8427 rsurface.fogheightfade = r_refdef.fogheightfade;
8428 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8429 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8430 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8431 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8432 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8433 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8434 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8435 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8436 rsurface.colormod[3] = 1;
8437 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);
8438 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8439 rsurface.frameblend[0].lerp = 1;
8440 rsurface.ent_alttextures = false;
8441 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8442 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8443 rsurface.entityskeletaltransform3x4 = NULL;
8444 rsurface.entityskeletaltransform3x4buffer = NULL;
8445 rsurface.entityskeletaltransform3x4offset = 0;
8446 rsurface.entityskeletaltransform3x4size = 0;;
8447 rsurface.entityskeletalnumtransforms = 0;
8448 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8449 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8450 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8451 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8452 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8453 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8454 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8455 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8456 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8457 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8458 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8459 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8460 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8461 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8462 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8463 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8464 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8465 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8466 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8467 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8468 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8469 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8470 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8471 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8472 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8473 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8475 rsurface.modelelement3i = model->surfmesh.data_element3i;
8476 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8477 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8478 rsurface.modelelement3s = model->surfmesh.data_element3s;
8479 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8480 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8481 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8482 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8483 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8484 rsurface.modelsurfaces = model->data_surfaces;
8485 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8486 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8487 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8488 rsurface.modelgeneratedvertex = false;
8489 rsurface.batchgeneratedvertex = false;
8490 rsurface.batchfirstvertex = 0;
8491 rsurface.batchnumvertices = 0;
8492 rsurface.batchfirsttriangle = 0;
8493 rsurface.batchnumtriangles = 0;
8494 rsurface.batchvertex3f = NULL;
8495 rsurface.batchvertex3f_vertexbuffer = NULL;
8496 rsurface.batchvertex3f_bufferoffset = 0;
8497 rsurface.batchsvector3f = NULL;
8498 rsurface.batchsvector3f_vertexbuffer = NULL;
8499 rsurface.batchsvector3f_bufferoffset = 0;
8500 rsurface.batchtvector3f = NULL;
8501 rsurface.batchtvector3f_vertexbuffer = NULL;
8502 rsurface.batchtvector3f_bufferoffset = 0;
8503 rsurface.batchnormal3f = NULL;
8504 rsurface.batchnormal3f_vertexbuffer = NULL;
8505 rsurface.batchnormal3f_bufferoffset = 0;
8506 rsurface.batchlightmapcolor4f = NULL;
8507 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8508 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8509 rsurface.batchtexcoordtexture2f = NULL;
8510 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8511 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8512 rsurface.batchtexcoordlightmap2f = NULL;
8513 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8514 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8515 rsurface.batchskeletalindex4ub = NULL;
8516 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8517 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8518 rsurface.batchskeletalweight4ub = NULL;
8519 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8520 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8521 rsurface.batchvertexmesh = NULL;
8522 rsurface.batchvertexmesh_vertexbuffer = NULL;
8523 rsurface.batchvertexmesh_bufferoffset = 0;
8524 rsurface.batchelement3i = NULL;
8525 rsurface.batchelement3i_indexbuffer = NULL;
8526 rsurface.batchelement3i_bufferoffset = 0;
8527 rsurface.batchelement3s = NULL;
8528 rsurface.batchelement3s_indexbuffer = NULL;
8529 rsurface.batchelement3s_bufferoffset = 0;
8530 rsurface.passcolor4f = NULL;
8531 rsurface.passcolor4f_vertexbuffer = NULL;
8532 rsurface.passcolor4f_bufferoffset = 0;
8533 rsurface.forcecurrenttextureupdate = false;
8536 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8538 dp_model_t *model = ent->model;
8539 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8541 rsurface.entity = (entity_render_t *)ent;
8542 rsurface.skeleton = ent->skeleton;
8543 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8544 rsurface.ent_skinnum = ent->skinnum;
8545 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;
8546 rsurface.ent_flags = ent->flags;
8547 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8548 rsurface.matrix = ent->matrix;
8549 rsurface.inversematrix = ent->inversematrix;
8550 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8551 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8552 R_EntityMatrix(&rsurface.matrix);
8553 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8554 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8555 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8556 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8557 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8558 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8559 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8560 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8561 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8562 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8563 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8564 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8565 rsurface.colormod[3] = ent->alpha;
8566 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8567 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8568 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8569 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8570 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8571 if (ent->model->brush.submodel && !prepass)
8573 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8574 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8576 // if the animcache code decided it should use the shader path, skip the deform step
8577 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8578 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8579 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8580 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8581 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8582 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8584 if (ent->animcache_vertex3f)
8586 r_refdef.stats[r_stat_batch_entitycache_count]++;
8587 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8588 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8589 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8590 rsurface.modelvertex3f = ent->animcache_vertex3f;
8591 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8592 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8593 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8594 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8595 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8596 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8597 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8598 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8599 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8600 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8601 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8602 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8603 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8604 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8606 else if (wanttangents)
8608 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8609 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8610 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8611 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8612 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8613 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8614 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8615 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8616 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8617 rsurface.modelvertexmesh = NULL;
8618 rsurface.modelvertexmesh_vertexbuffer = NULL;
8619 rsurface.modelvertexmesh_bufferoffset = 0;
8620 rsurface.modelvertex3f_vertexbuffer = NULL;
8621 rsurface.modelvertex3f_bufferoffset = 0;
8622 rsurface.modelvertex3f_vertexbuffer = 0;
8623 rsurface.modelvertex3f_bufferoffset = 0;
8624 rsurface.modelsvector3f_vertexbuffer = 0;
8625 rsurface.modelsvector3f_bufferoffset = 0;
8626 rsurface.modeltvector3f_vertexbuffer = 0;
8627 rsurface.modeltvector3f_bufferoffset = 0;
8628 rsurface.modelnormal3f_vertexbuffer = 0;
8629 rsurface.modelnormal3f_bufferoffset = 0;
8631 else if (wantnormals)
8633 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8634 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8635 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8636 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8637 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8638 rsurface.modelsvector3f = NULL;
8639 rsurface.modeltvector3f = NULL;
8640 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8641 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8642 rsurface.modelvertexmesh = NULL;
8643 rsurface.modelvertexmesh_vertexbuffer = NULL;
8644 rsurface.modelvertexmesh_bufferoffset = 0;
8645 rsurface.modelvertex3f_vertexbuffer = NULL;
8646 rsurface.modelvertex3f_bufferoffset = 0;
8647 rsurface.modelvertex3f_vertexbuffer = 0;
8648 rsurface.modelvertex3f_bufferoffset = 0;
8649 rsurface.modelsvector3f_vertexbuffer = 0;
8650 rsurface.modelsvector3f_bufferoffset = 0;
8651 rsurface.modeltvector3f_vertexbuffer = 0;
8652 rsurface.modeltvector3f_bufferoffset = 0;
8653 rsurface.modelnormal3f_vertexbuffer = 0;
8654 rsurface.modelnormal3f_bufferoffset = 0;
8658 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8659 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8660 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8661 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8662 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8663 rsurface.modelsvector3f = NULL;
8664 rsurface.modeltvector3f = NULL;
8665 rsurface.modelnormal3f = NULL;
8666 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8667 rsurface.modelvertexmesh = NULL;
8668 rsurface.modelvertexmesh_vertexbuffer = NULL;
8669 rsurface.modelvertexmesh_bufferoffset = 0;
8670 rsurface.modelvertex3f_vertexbuffer = NULL;
8671 rsurface.modelvertex3f_bufferoffset = 0;
8672 rsurface.modelvertex3f_vertexbuffer = 0;
8673 rsurface.modelvertex3f_bufferoffset = 0;
8674 rsurface.modelsvector3f_vertexbuffer = 0;
8675 rsurface.modelsvector3f_bufferoffset = 0;
8676 rsurface.modeltvector3f_vertexbuffer = 0;
8677 rsurface.modeltvector3f_bufferoffset = 0;
8678 rsurface.modelnormal3f_vertexbuffer = 0;
8679 rsurface.modelnormal3f_bufferoffset = 0;
8681 rsurface.modelgeneratedvertex = true;
8685 if (rsurface.entityskeletaltransform3x4)
8687 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8688 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8689 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8690 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8694 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8695 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8696 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8697 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8699 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8700 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8701 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8702 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8703 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8704 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8705 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8706 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8707 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8708 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8709 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8710 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8711 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8712 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8713 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8714 rsurface.modelgeneratedvertex = false;
8716 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8717 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8718 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8719 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8720 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8721 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8722 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8723 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8724 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8725 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8726 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8727 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8728 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8729 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8730 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8731 rsurface.modelelement3i = model->surfmesh.data_element3i;
8732 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8733 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8734 rsurface.modelelement3s = model->surfmesh.data_element3s;
8735 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8736 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8737 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8738 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8739 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8740 rsurface.modelsurfaces = model->data_surfaces;
8741 rsurface.batchgeneratedvertex = false;
8742 rsurface.batchfirstvertex = 0;
8743 rsurface.batchnumvertices = 0;
8744 rsurface.batchfirsttriangle = 0;
8745 rsurface.batchnumtriangles = 0;
8746 rsurface.batchvertex3f = NULL;
8747 rsurface.batchvertex3f_vertexbuffer = NULL;
8748 rsurface.batchvertex3f_bufferoffset = 0;
8749 rsurface.batchsvector3f = NULL;
8750 rsurface.batchsvector3f_vertexbuffer = NULL;
8751 rsurface.batchsvector3f_bufferoffset = 0;
8752 rsurface.batchtvector3f = NULL;
8753 rsurface.batchtvector3f_vertexbuffer = NULL;
8754 rsurface.batchtvector3f_bufferoffset = 0;
8755 rsurface.batchnormal3f = NULL;
8756 rsurface.batchnormal3f_vertexbuffer = NULL;
8757 rsurface.batchnormal3f_bufferoffset = 0;
8758 rsurface.batchlightmapcolor4f = NULL;
8759 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8760 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8761 rsurface.batchtexcoordtexture2f = NULL;
8762 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8763 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8764 rsurface.batchtexcoordlightmap2f = NULL;
8765 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8766 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8767 rsurface.batchskeletalindex4ub = NULL;
8768 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8769 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8770 rsurface.batchskeletalweight4ub = NULL;
8771 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8772 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8773 rsurface.batchvertexmesh = NULL;
8774 rsurface.batchvertexmesh_vertexbuffer = NULL;
8775 rsurface.batchvertexmesh_bufferoffset = 0;
8776 rsurface.batchelement3i = NULL;
8777 rsurface.batchelement3i_indexbuffer = NULL;
8778 rsurface.batchelement3i_bufferoffset = 0;
8779 rsurface.batchelement3s = NULL;
8780 rsurface.batchelement3s_indexbuffer = NULL;
8781 rsurface.batchelement3s_bufferoffset = 0;
8782 rsurface.passcolor4f = NULL;
8783 rsurface.passcolor4f_vertexbuffer = NULL;
8784 rsurface.passcolor4f_bufferoffset = 0;
8785 rsurface.forcecurrenttextureupdate = false;
8788 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)
8790 rsurface.entity = r_refdef.scene.worldentity;
8791 rsurface.skeleton = NULL;
8792 rsurface.ent_skinnum = 0;
8793 rsurface.ent_qwskin = -1;
8794 rsurface.ent_flags = entflags;
8795 rsurface.shadertime = r_refdef.scene.time - shadertime;
8796 rsurface.modelnumvertices = numvertices;
8797 rsurface.modelnumtriangles = numtriangles;
8798 rsurface.matrix = *matrix;
8799 rsurface.inversematrix = *inversematrix;
8800 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8801 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8802 R_EntityMatrix(&rsurface.matrix);
8803 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8804 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8805 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8806 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8807 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8808 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8809 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8810 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8811 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8812 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8813 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8814 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8815 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);
8816 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8817 rsurface.frameblend[0].lerp = 1;
8818 rsurface.ent_alttextures = false;
8819 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8820 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8821 rsurface.entityskeletaltransform3x4 = NULL;
8822 rsurface.entityskeletaltransform3x4buffer = NULL;
8823 rsurface.entityskeletaltransform3x4offset = 0;
8824 rsurface.entityskeletaltransform3x4size = 0;
8825 rsurface.entityskeletalnumtransforms = 0;
8826 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8827 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8828 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8829 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8832 rsurface.modelvertex3f = (float *)vertex3f;
8833 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8834 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8835 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8837 else if (wantnormals)
8839 rsurface.modelvertex3f = (float *)vertex3f;
8840 rsurface.modelsvector3f = NULL;
8841 rsurface.modeltvector3f = NULL;
8842 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8846 rsurface.modelvertex3f = (float *)vertex3f;
8847 rsurface.modelsvector3f = NULL;
8848 rsurface.modeltvector3f = NULL;
8849 rsurface.modelnormal3f = NULL;
8851 rsurface.modelvertexmesh = NULL;
8852 rsurface.modelvertexmesh_vertexbuffer = NULL;
8853 rsurface.modelvertexmesh_bufferoffset = 0;
8854 rsurface.modelvertex3f_vertexbuffer = 0;
8855 rsurface.modelvertex3f_bufferoffset = 0;
8856 rsurface.modelsvector3f_vertexbuffer = 0;
8857 rsurface.modelsvector3f_bufferoffset = 0;
8858 rsurface.modeltvector3f_vertexbuffer = 0;
8859 rsurface.modeltvector3f_bufferoffset = 0;
8860 rsurface.modelnormal3f_vertexbuffer = 0;
8861 rsurface.modelnormal3f_bufferoffset = 0;
8862 rsurface.modelgeneratedvertex = true;
8863 rsurface.modellightmapcolor4f = (float *)color4f;
8864 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8865 rsurface.modellightmapcolor4f_bufferoffset = 0;
8866 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8867 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8868 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8869 rsurface.modeltexcoordlightmap2f = NULL;
8870 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8871 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8872 rsurface.modelskeletalindex4ub = NULL;
8873 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8874 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8875 rsurface.modelskeletalweight4ub = NULL;
8876 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8877 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8878 rsurface.modelelement3i = (int *)element3i;
8879 rsurface.modelelement3i_indexbuffer = NULL;
8880 rsurface.modelelement3i_bufferoffset = 0;
8881 rsurface.modelelement3s = (unsigned short *)element3s;
8882 rsurface.modelelement3s_indexbuffer = NULL;
8883 rsurface.modelelement3s_bufferoffset = 0;
8884 rsurface.modellightmapoffsets = NULL;
8885 rsurface.modelsurfaces = NULL;
8886 rsurface.batchgeneratedvertex = false;
8887 rsurface.batchfirstvertex = 0;
8888 rsurface.batchnumvertices = 0;
8889 rsurface.batchfirsttriangle = 0;
8890 rsurface.batchnumtriangles = 0;
8891 rsurface.batchvertex3f = NULL;
8892 rsurface.batchvertex3f_vertexbuffer = NULL;
8893 rsurface.batchvertex3f_bufferoffset = 0;
8894 rsurface.batchsvector3f = NULL;
8895 rsurface.batchsvector3f_vertexbuffer = NULL;
8896 rsurface.batchsvector3f_bufferoffset = 0;
8897 rsurface.batchtvector3f = NULL;
8898 rsurface.batchtvector3f_vertexbuffer = NULL;
8899 rsurface.batchtvector3f_bufferoffset = 0;
8900 rsurface.batchnormal3f = NULL;
8901 rsurface.batchnormal3f_vertexbuffer = NULL;
8902 rsurface.batchnormal3f_bufferoffset = 0;
8903 rsurface.batchlightmapcolor4f = NULL;
8904 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8905 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8906 rsurface.batchtexcoordtexture2f = NULL;
8907 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8908 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8909 rsurface.batchtexcoordlightmap2f = NULL;
8910 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8911 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8912 rsurface.batchskeletalindex4ub = NULL;
8913 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8914 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8915 rsurface.batchskeletalweight4ub = NULL;
8916 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8917 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8918 rsurface.batchvertexmesh = NULL;
8919 rsurface.batchvertexmesh_vertexbuffer = NULL;
8920 rsurface.batchvertexmesh_bufferoffset = 0;
8921 rsurface.batchelement3i = NULL;
8922 rsurface.batchelement3i_indexbuffer = NULL;
8923 rsurface.batchelement3i_bufferoffset = 0;
8924 rsurface.batchelement3s = NULL;
8925 rsurface.batchelement3s_indexbuffer = NULL;
8926 rsurface.batchelement3s_bufferoffset = 0;
8927 rsurface.passcolor4f = NULL;
8928 rsurface.passcolor4f_vertexbuffer = NULL;
8929 rsurface.passcolor4f_bufferoffset = 0;
8930 rsurface.forcecurrenttextureupdate = true;
8932 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8934 if ((wantnormals || wanttangents) && !normal3f)
8936 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8937 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8939 if (wanttangents && !svector3f)
8941 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8942 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8943 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8948 float RSurf_FogPoint(const float *v)
8950 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8951 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8952 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8953 float FogHeightFade = r_refdef.fogheightfade;
8955 unsigned int fogmasktableindex;
8956 if (r_refdef.fogplaneviewabove)
8957 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8959 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8960 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8961 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8964 float RSurf_FogVertex(const float *v)
8966 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8967 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8968 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8969 float FogHeightFade = rsurface.fogheightfade;
8971 unsigned int fogmasktableindex;
8972 if (r_refdef.fogplaneviewabove)
8973 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8975 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8976 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8977 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8980 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8983 for (i = 0;i < numelements;i++)
8984 outelement3i[i] = inelement3i[i] + adjust;
8987 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8988 extern cvar_t gl_vbo;
8989 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8997 int surfacefirsttriangle;
8998 int surfacenumtriangles;
8999 int surfacefirstvertex;
9000 int surfaceendvertex;
9001 int surfacenumvertices;
9002 int batchnumsurfaces = texturenumsurfaces;
9003 int batchnumvertices;
9004 int batchnumtriangles;
9008 qboolean dynamicvertex;
9012 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9015 q3shaderinfo_deform_t *deform;
9016 const msurface_t *surface, *firstsurface;
9017 r_vertexmesh_t *vertexmesh;
9018 if (!texturenumsurfaces)
9020 // find vertex range of this surface batch
9022 firstsurface = texturesurfacelist[0];
9023 firsttriangle = firstsurface->num_firsttriangle;
9024 batchnumvertices = 0;
9025 batchnumtriangles = 0;
9026 firstvertex = endvertex = firstsurface->num_firstvertex;
9027 for (i = 0;i < texturenumsurfaces;i++)
9029 surface = texturesurfacelist[i];
9030 if (surface != firstsurface + i)
9032 surfacefirstvertex = surface->num_firstvertex;
9033 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9034 surfacenumvertices = surface->num_vertices;
9035 surfacenumtriangles = surface->num_triangles;
9036 if (firstvertex > surfacefirstvertex)
9037 firstvertex = surfacefirstvertex;
9038 if (endvertex < surfaceendvertex)
9039 endvertex = surfaceendvertex;
9040 batchnumvertices += surfacenumvertices;
9041 batchnumtriangles += surfacenumtriangles;
9044 r_refdef.stats[r_stat_batch_batches]++;
9046 r_refdef.stats[r_stat_batch_withgaps]++;
9047 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9048 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9049 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9051 // we now know the vertex range used, and if there are any gaps in it
9052 rsurface.batchfirstvertex = firstvertex;
9053 rsurface.batchnumvertices = endvertex - firstvertex;
9054 rsurface.batchfirsttriangle = firsttriangle;
9055 rsurface.batchnumtriangles = batchnumtriangles;
9057 // this variable holds flags for which properties have been updated that
9058 // may require regenerating vertexmesh array...
9061 // check if any dynamic vertex processing must occur
9062 dynamicvertex = false;
9064 // a cvar to force the dynamic vertex path to be taken, for debugging
9065 if (r_batch_debugdynamicvertexpath.integer)
9069 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9070 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9071 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9072 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9074 dynamicvertex = true;
9077 // if there is a chance of animated vertex colors, it's a dynamic batch
9078 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9082 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9083 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9084 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9085 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9087 dynamicvertex = true;
9088 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9091 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9093 switch (deform->deform)
9096 case Q3DEFORM_PROJECTIONSHADOW:
9097 case Q3DEFORM_TEXT0:
9098 case Q3DEFORM_TEXT1:
9099 case Q3DEFORM_TEXT2:
9100 case Q3DEFORM_TEXT3:
9101 case Q3DEFORM_TEXT4:
9102 case Q3DEFORM_TEXT5:
9103 case Q3DEFORM_TEXT6:
9104 case Q3DEFORM_TEXT7:
9107 case Q3DEFORM_AUTOSPRITE:
9110 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9111 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9112 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9113 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9115 dynamicvertex = true;
9116 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9117 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9119 case Q3DEFORM_AUTOSPRITE2:
9122 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9123 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9124 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9125 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9127 dynamicvertex = true;
9128 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9129 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9131 case Q3DEFORM_NORMAL:
9134 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9135 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9136 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9137 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9139 dynamicvertex = true;
9140 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9141 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9144 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9145 break; // if wavefunc is a nop, ignore this transform
9148 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9149 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9150 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9151 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9153 dynamicvertex = true;
9154 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9155 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9157 case Q3DEFORM_BULGE:
9160 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9161 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9162 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9163 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9165 dynamicvertex = true;
9166 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9167 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9170 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9171 break; // if wavefunc is a nop, ignore this transform
9174 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9175 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9176 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9177 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9179 dynamicvertex = true;
9180 batchneed |= BATCHNEED_ARRAY_VERTEX;
9181 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9185 switch(rsurface.texture->tcgen.tcgen)
9188 case Q3TCGEN_TEXTURE:
9190 case Q3TCGEN_LIGHTMAP:
9193 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9194 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9195 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9196 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9198 dynamicvertex = true;
9199 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9200 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9202 case Q3TCGEN_VECTOR:
9205 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9206 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9207 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9208 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9210 dynamicvertex = true;
9211 batchneed |= BATCHNEED_ARRAY_VERTEX;
9212 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9214 case Q3TCGEN_ENVIRONMENT:
9217 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9218 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9219 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9220 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9222 dynamicvertex = true;
9223 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9224 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9227 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9231 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9232 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9233 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9234 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9236 dynamicvertex = true;
9237 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9238 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9241 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9245 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9246 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9247 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9248 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9250 dynamicvertex = true;
9251 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9254 // when the model data has no vertex buffer (dynamic mesh), we need to
9256 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9257 batchneed |= BATCHNEED_NOGAPS;
9259 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9260 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9261 // we ensure this by treating the vertex batch as dynamic...
9262 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9266 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9267 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9268 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9269 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9271 dynamicvertex = true;
9276 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9277 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9278 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9279 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9280 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9281 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9282 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9283 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9286 // if needsupdate, we have to do a dynamic vertex batch for sure
9287 if (needsupdate & batchneed)
9291 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9292 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9293 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9294 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9296 dynamicvertex = true;
9299 // see if we need to build vertexmesh from arrays
9300 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9304 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9305 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9306 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9307 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9309 dynamicvertex = true;
9312 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9313 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9314 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9316 rsurface.batchvertex3f = rsurface.modelvertex3f;
9317 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9318 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9319 rsurface.batchsvector3f = rsurface.modelsvector3f;
9320 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9321 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9322 rsurface.batchtvector3f = rsurface.modeltvector3f;
9323 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9324 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9325 rsurface.batchnormal3f = rsurface.modelnormal3f;
9326 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9327 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9328 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9329 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9330 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9331 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9332 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9333 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9334 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9335 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9336 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9337 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9338 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9339 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9340 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9341 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9342 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9343 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9344 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9345 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9346 rsurface.batchelement3i = rsurface.modelelement3i;
9347 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9348 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9349 rsurface.batchelement3s = rsurface.modelelement3s;
9350 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9351 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9352 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9353 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9354 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9355 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9356 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9358 // if any dynamic vertex processing has to occur in software, we copy the
9359 // entire surface list together before processing to rebase the vertices
9360 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9362 // if any gaps exist and we do not have a static vertex buffer, we have to
9363 // copy the surface list together to avoid wasting upload bandwidth on the
9364 // vertices in the gaps.
9366 // if gaps exist and we have a static vertex buffer, we can choose whether
9367 // to combine the index buffer ranges into one dynamic index buffer or
9368 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9370 // in many cases the batch is reduced to one draw call.
9372 rsurface.batchmultidraw = false;
9373 rsurface.batchmultidrawnumsurfaces = 0;
9374 rsurface.batchmultidrawsurfacelist = NULL;
9378 // static vertex data, just set pointers...
9379 rsurface.batchgeneratedvertex = false;
9380 // if there are gaps, we want to build a combined index buffer,
9381 // otherwise use the original static buffer with an appropriate offset
9384 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9385 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9386 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9387 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9388 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9390 rsurface.batchmultidraw = true;
9391 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9392 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9395 // build a new triangle elements array for this batch
9396 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9397 rsurface.batchfirsttriangle = 0;
9399 for (i = 0;i < texturenumsurfaces;i++)
9401 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9402 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9403 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9404 numtriangles += surfacenumtriangles;
9406 rsurface.batchelement3i_indexbuffer = NULL;
9407 rsurface.batchelement3i_bufferoffset = 0;
9408 rsurface.batchelement3s = NULL;
9409 rsurface.batchelement3s_indexbuffer = NULL;
9410 rsurface.batchelement3s_bufferoffset = 0;
9411 if (endvertex <= 65536)
9413 // make a 16bit (unsigned short) index array if possible
9414 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9415 for (i = 0;i < numtriangles*3;i++)
9416 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9418 // upload buffer data for the copytriangles batch
9419 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9421 if (rsurface.batchelement3s)
9422 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9423 else if (rsurface.batchelement3i)
9424 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9429 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9430 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9431 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9432 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9437 // something needs software processing, do it for real...
9438 // we only directly handle separate array data in this case and then
9439 // generate interleaved data if needed...
9440 rsurface.batchgeneratedvertex = true;
9441 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9442 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9443 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9444 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9446 // now copy the vertex data into a combined array and make an index array
9447 // (this is what Quake3 does all the time)
9448 // we also apply any skeletal animation here that would have been done in
9449 // the vertex shader, because most of the dynamic vertex animation cases
9450 // need actual vertex positions and normals
9451 //if (dynamicvertex)
9453 rsurface.batchvertexmesh = NULL;
9454 rsurface.batchvertexmesh_vertexbuffer = NULL;
9455 rsurface.batchvertexmesh_bufferoffset = 0;
9456 rsurface.batchvertex3f = NULL;
9457 rsurface.batchvertex3f_vertexbuffer = NULL;
9458 rsurface.batchvertex3f_bufferoffset = 0;
9459 rsurface.batchsvector3f = NULL;
9460 rsurface.batchsvector3f_vertexbuffer = NULL;
9461 rsurface.batchsvector3f_bufferoffset = 0;
9462 rsurface.batchtvector3f = NULL;
9463 rsurface.batchtvector3f_vertexbuffer = NULL;
9464 rsurface.batchtvector3f_bufferoffset = 0;
9465 rsurface.batchnormal3f = NULL;
9466 rsurface.batchnormal3f_vertexbuffer = NULL;
9467 rsurface.batchnormal3f_bufferoffset = 0;
9468 rsurface.batchlightmapcolor4f = NULL;
9469 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9470 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9471 rsurface.batchtexcoordtexture2f = NULL;
9472 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9473 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9474 rsurface.batchtexcoordlightmap2f = NULL;
9475 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9476 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9477 rsurface.batchskeletalindex4ub = NULL;
9478 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9479 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9480 rsurface.batchskeletalweight4ub = NULL;
9481 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9482 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9483 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9484 rsurface.batchelement3i_indexbuffer = NULL;
9485 rsurface.batchelement3i_bufferoffset = 0;
9486 rsurface.batchelement3s = NULL;
9487 rsurface.batchelement3s_indexbuffer = NULL;
9488 rsurface.batchelement3s_bufferoffset = 0;
9489 rsurface.batchskeletaltransform3x4buffer = NULL;
9490 rsurface.batchskeletaltransform3x4offset = 0;
9491 rsurface.batchskeletaltransform3x4size = 0;
9492 // we'll only be setting up certain arrays as needed
9493 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9494 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9495 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9496 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9497 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9498 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9499 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9501 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9502 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9504 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9505 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9506 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9507 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9508 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9509 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9510 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9512 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9513 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9517 for (i = 0;i < texturenumsurfaces;i++)
9519 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9520 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9521 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9522 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9523 // copy only the data requested
9524 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9525 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9526 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9528 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9530 if (rsurface.batchvertex3f)
9531 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9533 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9535 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9537 if (rsurface.modelnormal3f)
9538 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9540 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9542 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9544 if (rsurface.modelsvector3f)
9546 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9547 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9551 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9552 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9555 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9557 if (rsurface.modellightmapcolor4f)
9558 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9560 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9562 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9564 if (rsurface.modeltexcoordtexture2f)
9565 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9567 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9569 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9571 if (rsurface.modeltexcoordlightmap2f)
9572 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9574 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9576 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9578 if (rsurface.modelskeletalindex4ub)
9580 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9581 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9585 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9586 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9587 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9588 for (j = 0;j < surfacenumvertices;j++)
9593 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9594 numvertices += surfacenumvertices;
9595 numtriangles += surfacenumtriangles;
9598 // generate a 16bit index array as well if possible
9599 // (in general, dynamic batches fit)
9600 if (numvertices <= 65536)
9602 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9603 for (i = 0;i < numtriangles*3;i++)
9604 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9607 // since we've copied everything, the batch now starts at 0
9608 rsurface.batchfirstvertex = 0;
9609 rsurface.batchnumvertices = batchnumvertices;
9610 rsurface.batchfirsttriangle = 0;
9611 rsurface.batchnumtriangles = batchnumtriangles;
9614 // apply skeletal animation that would have been done in the vertex shader
9615 if (rsurface.batchskeletaltransform3x4)
9617 const unsigned char *si;
9618 const unsigned char *sw;
9620 const float *b = rsurface.batchskeletaltransform3x4;
9621 float *vp, *vs, *vt, *vn;
9623 float m[3][4], n[3][4];
9624 float tp[3], ts[3], tt[3], tn[3];
9625 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9626 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9627 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9628 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9629 si = rsurface.batchskeletalindex4ub;
9630 sw = rsurface.batchskeletalweight4ub;
9631 vp = rsurface.batchvertex3f;
9632 vs = rsurface.batchsvector3f;
9633 vt = rsurface.batchtvector3f;
9634 vn = rsurface.batchnormal3f;
9635 memset(m[0], 0, sizeof(m));
9636 memset(n[0], 0, sizeof(n));
9637 for (i = 0;i < batchnumvertices;i++)
9639 t[0] = b + si[0]*12;
9642 // common case - only one matrix
9656 else if (sw[2] + sw[3])
9659 t[1] = b + si[1]*12;
9660 t[2] = b + si[2]*12;
9661 t[3] = b + si[3]*12;
9662 w[0] = sw[0] * (1.0f / 255.0f);
9663 w[1] = sw[1] * (1.0f / 255.0f);
9664 w[2] = sw[2] * (1.0f / 255.0f);
9665 w[3] = sw[3] * (1.0f / 255.0f);
9666 // blend the matrices
9667 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9668 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9669 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9670 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9671 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9672 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9673 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9674 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9675 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9676 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9677 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9678 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9683 t[1] = b + si[1]*12;
9684 w[0] = sw[0] * (1.0f / 255.0f);
9685 w[1] = sw[1] * (1.0f / 255.0f);
9686 // blend the matrices
9687 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9688 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9689 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9690 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9691 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9692 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9693 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9694 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9695 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9696 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9697 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9698 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9702 // modify the vertex
9704 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9705 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9706 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9710 // the normal transformation matrix is a set of cross products...
9711 CrossProduct(m[1], m[2], n[0]);
9712 CrossProduct(m[2], m[0], n[1]);
9713 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9715 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9716 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9717 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9718 VectorNormalize(vn);
9723 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9724 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9725 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9726 VectorNormalize(vs);
9729 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9730 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9731 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9732 VectorNormalize(vt);
9737 rsurface.batchskeletaltransform3x4 = NULL;
9738 rsurface.batchskeletalnumtransforms = 0;
9741 // q1bsp surfaces rendered in vertex color mode have to have colors
9742 // calculated based on lightstyles
9743 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9745 // generate color arrays for the surfaces in this list
9750 const unsigned char *lm;
9751 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9752 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9753 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9755 for (i = 0;i < texturenumsurfaces;i++)
9757 surface = texturesurfacelist[i];
9758 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9759 surfacenumvertices = surface->num_vertices;
9760 if (surface->lightmapinfo->samples)
9762 for (j = 0;j < surfacenumvertices;j++)
9764 lm = surface->lightmapinfo->samples + offsets[j];
9765 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9766 VectorScale(lm, scale, c);
9767 if (surface->lightmapinfo->styles[1] != 255)
9769 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9771 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9772 VectorMA(c, scale, lm, c);
9773 if (surface->lightmapinfo->styles[2] != 255)
9776 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9777 VectorMA(c, scale, lm, c);
9778 if (surface->lightmapinfo->styles[3] != 255)
9781 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9782 VectorMA(c, scale, lm, c);
9789 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);
9795 for (j = 0;j < surfacenumvertices;j++)
9797 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9804 // if vertices are deformed (sprite flares and things in maps, possibly
9805 // water waves, bulges and other deformations), modify the copied vertices
9807 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9809 switch (deform->deform)
9812 case Q3DEFORM_PROJECTIONSHADOW:
9813 case Q3DEFORM_TEXT0:
9814 case Q3DEFORM_TEXT1:
9815 case Q3DEFORM_TEXT2:
9816 case Q3DEFORM_TEXT3:
9817 case Q3DEFORM_TEXT4:
9818 case Q3DEFORM_TEXT5:
9819 case Q3DEFORM_TEXT6:
9820 case Q3DEFORM_TEXT7:
9823 case Q3DEFORM_AUTOSPRITE:
9824 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9825 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9826 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9827 VectorNormalize(newforward);
9828 VectorNormalize(newright);
9829 VectorNormalize(newup);
9830 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9831 // rsurface.batchvertex3f_vertexbuffer = NULL;
9832 // rsurface.batchvertex3f_bufferoffset = 0;
9833 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9834 // rsurface.batchsvector3f_vertexbuffer = NULL;
9835 // rsurface.batchsvector3f_bufferoffset = 0;
9836 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9837 // rsurface.batchtvector3f_vertexbuffer = NULL;
9838 // rsurface.batchtvector3f_bufferoffset = 0;
9839 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9840 // rsurface.batchnormal3f_vertexbuffer = NULL;
9841 // rsurface.batchnormal3f_bufferoffset = 0;
9842 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9843 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9844 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9845 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9846 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);
9847 // a single autosprite surface can contain multiple sprites...
9848 for (j = 0;j < batchnumvertices - 3;j += 4)
9850 VectorClear(center);
9851 for (i = 0;i < 4;i++)
9852 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9853 VectorScale(center, 0.25f, center);
9854 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9855 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9856 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9857 for (i = 0;i < 4;i++)
9859 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9860 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9863 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9864 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9865 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);
9867 case Q3DEFORM_AUTOSPRITE2:
9868 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9869 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9870 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9871 VectorNormalize(newforward);
9872 VectorNormalize(newright);
9873 VectorNormalize(newup);
9874 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9875 // rsurface.batchvertex3f_vertexbuffer = NULL;
9876 // rsurface.batchvertex3f_bufferoffset = 0;
9878 const float *v1, *v2;
9888 memset(shortest, 0, sizeof(shortest));
9889 // a single autosprite surface can contain multiple sprites...
9890 for (j = 0;j < batchnumvertices - 3;j += 4)
9892 VectorClear(center);
9893 for (i = 0;i < 4;i++)
9894 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9895 VectorScale(center, 0.25f, center);
9896 // find the two shortest edges, then use them to define the
9897 // axis vectors for rotating around the central axis
9898 for (i = 0;i < 6;i++)
9900 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9901 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9902 l = VectorDistance2(v1, v2);
9903 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9905 l += (1.0f / 1024.0f);
9906 if (shortest[0].length2 > l || i == 0)
9908 shortest[1] = shortest[0];
9909 shortest[0].length2 = l;
9910 shortest[0].v1 = v1;
9911 shortest[0].v2 = v2;
9913 else if (shortest[1].length2 > l || i == 1)
9915 shortest[1].length2 = l;
9916 shortest[1].v1 = v1;
9917 shortest[1].v2 = v2;
9920 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9921 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9922 // this calculates the right vector from the shortest edge
9923 // and the up vector from the edge midpoints
9924 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9925 VectorNormalize(right);
9926 VectorSubtract(end, start, up);
9927 VectorNormalize(up);
9928 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9929 VectorSubtract(rsurface.localvieworigin, center, forward);
9930 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9931 VectorNegate(forward, forward);
9932 VectorReflect(forward, 0, up, forward);
9933 VectorNormalize(forward);
9934 CrossProduct(up, forward, newright);
9935 VectorNormalize(newright);
9936 // rotate the quad around the up axis vector, this is made
9937 // especially easy by the fact we know the quad is flat,
9938 // so we only have to subtract the center position and
9939 // measure distance along the right vector, and then
9940 // multiply that by the newright vector and add back the
9942 // we also need to subtract the old position to undo the
9943 // displacement from the center, which we do with a
9944 // DotProduct, the subtraction/addition of center is also
9945 // optimized into DotProducts here
9946 l = DotProduct(right, center);
9947 for (i = 0;i < 4;i++)
9949 v1 = rsurface.batchvertex3f + 3*(j+i);
9950 f = DotProduct(right, v1) - l;
9951 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9955 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9957 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9958 // rsurface.batchnormal3f_vertexbuffer = NULL;
9959 // rsurface.batchnormal3f_bufferoffset = 0;
9960 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9962 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9964 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9965 // rsurface.batchsvector3f_vertexbuffer = NULL;
9966 // rsurface.batchsvector3f_bufferoffset = 0;
9967 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9968 // rsurface.batchtvector3f_vertexbuffer = NULL;
9969 // rsurface.batchtvector3f_bufferoffset = 0;
9970 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);
9973 case Q3DEFORM_NORMAL:
9974 // deform the normals to make reflections wavey
9975 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9976 rsurface.batchnormal3f_vertexbuffer = NULL;
9977 rsurface.batchnormal3f_bufferoffset = 0;
9978 for (j = 0;j < batchnumvertices;j++)
9981 float *normal = rsurface.batchnormal3f + 3*j;
9982 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9983 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9984 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9985 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9986 VectorNormalize(normal);
9988 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9990 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9991 // rsurface.batchsvector3f_vertexbuffer = NULL;
9992 // rsurface.batchsvector3f_bufferoffset = 0;
9993 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9994 // rsurface.batchtvector3f_vertexbuffer = NULL;
9995 // rsurface.batchtvector3f_bufferoffset = 0;
9996 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);
10000 // deform vertex array to make wavey water and flags and such
10001 waveparms[0] = deform->waveparms[0];
10002 waveparms[1] = deform->waveparms[1];
10003 waveparms[2] = deform->waveparms[2];
10004 waveparms[3] = deform->waveparms[3];
10005 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10006 break; // if wavefunc is a nop, don't make a dynamic vertex array
10007 // this is how a divisor of vertex influence on deformation
10008 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10009 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10010 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10011 // rsurface.batchvertex3f_vertexbuffer = NULL;
10012 // rsurface.batchvertex3f_bufferoffset = 0;
10013 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10014 // rsurface.batchnormal3f_vertexbuffer = NULL;
10015 // rsurface.batchnormal3f_bufferoffset = 0;
10016 for (j = 0;j < batchnumvertices;j++)
10018 // if the wavefunc depends on time, evaluate it per-vertex
10021 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10022 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10024 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10026 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10027 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10028 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10030 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10031 // rsurface.batchsvector3f_vertexbuffer = NULL;
10032 // rsurface.batchsvector3f_bufferoffset = 0;
10033 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10034 // rsurface.batchtvector3f_vertexbuffer = NULL;
10035 // rsurface.batchtvector3f_bufferoffset = 0;
10036 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);
10039 case Q3DEFORM_BULGE:
10040 // deform vertex array to make the surface have moving bulges
10041 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10042 // rsurface.batchvertex3f_vertexbuffer = NULL;
10043 // rsurface.batchvertex3f_bufferoffset = 0;
10044 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10045 // rsurface.batchnormal3f_vertexbuffer = NULL;
10046 // rsurface.batchnormal3f_bufferoffset = 0;
10047 for (j = 0;j < batchnumvertices;j++)
10049 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10050 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10052 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10053 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10054 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10056 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10057 // rsurface.batchsvector3f_vertexbuffer = NULL;
10058 // rsurface.batchsvector3f_bufferoffset = 0;
10059 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10060 // rsurface.batchtvector3f_vertexbuffer = NULL;
10061 // rsurface.batchtvector3f_bufferoffset = 0;
10062 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);
10065 case Q3DEFORM_MOVE:
10066 // deform vertex array
10067 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10068 break; // if wavefunc is a nop, don't make a dynamic vertex array
10069 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10070 VectorScale(deform->parms, scale, waveparms);
10071 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10072 // rsurface.batchvertex3f_vertexbuffer = NULL;
10073 // rsurface.batchvertex3f_bufferoffset = 0;
10074 for (j = 0;j < batchnumvertices;j++)
10075 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10080 // generate texcoords based on the chosen texcoord source
10081 switch(rsurface.texture->tcgen.tcgen)
10084 case Q3TCGEN_TEXTURE:
10086 case Q3TCGEN_LIGHTMAP:
10087 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10088 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10089 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10090 if (rsurface.batchtexcoordlightmap2f)
10091 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
10093 case Q3TCGEN_VECTOR:
10094 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10095 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10096 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10097 for (j = 0;j < batchnumvertices;j++)
10099 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10100 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10103 case Q3TCGEN_ENVIRONMENT:
10104 // make environment reflections using a spheremap
10105 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10106 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10107 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10108 for (j = 0;j < batchnumvertices;j++)
10110 // identical to Q3A's method, but executed in worldspace so
10111 // carried models can be shiny too
10113 float viewer[3], d, reflected[3], worldreflected[3];
10115 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10116 // VectorNormalize(viewer);
10118 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10120 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10121 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10122 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10123 // note: this is proportinal to viewer, so we can normalize later
10125 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10126 VectorNormalize(worldreflected);
10128 // note: this sphere map only uses world x and z!
10129 // so positive and negative y will LOOK THE SAME.
10130 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10131 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10135 // the only tcmod that needs software vertex processing is turbulent, so
10136 // check for it here and apply the changes if needed
10137 // and we only support that as the first one
10138 // (handling a mixture of turbulent and other tcmods would be problematic
10139 // without punting it entirely to a software path)
10140 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10142 amplitude = rsurface.texture->tcmods[0].parms[1];
10143 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10144 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10145 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10146 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10147 for (j = 0;j < batchnumvertices;j++)
10149 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);
10150 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10154 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10156 // convert the modified arrays to vertex structs
10157 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10158 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10159 // rsurface.batchvertexmesh_bufferoffset = 0;
10160 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10161 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10162 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10163 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10164 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10165 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10166 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10168 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10170 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10171 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10174 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10175 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10176 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10177 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10178 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10179 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10180 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10181 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10182 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10183 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10185 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10187 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10188 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10193 // upload buffer data for the dynamic batch
10194 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10196 if (rsurface.batchvertexmesh)
10197 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10200 if (rsurface.batchvertex3f)
10201 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10202 if (rsurface.batchsvector3f)
10203 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10204 if (rsurface.batchtvector3f)
10205 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10206 if (rsurface.batchnormal3f)
10207 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10208 if (rsurface.batchlightmapcolor4f)
10209 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10210 if (rsurface.batchtexcoordtexture2f)
10211 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10212 if (rsurface.batchtexcoordlightmap2f)
10213 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10214 if (rsurface.batchskeletalindex4ub)
10215 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10216 if (rsurface.batchskeletalweight4ub)
10217 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10219 if (rsurface.batchelement3s)
10220 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10221 else if (rsurface.batchelement3i)
10222 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10226 void RSurf_DrawBatch(void)
10228 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10229 // through the pipeline, killing it earlier in the pipeline would have
10230 // per-surface overhead rather than per-batch overhead, so it's best to
10231 // reject it here, before it hits glDraw.
10232 if (rsurface.batchnumtriangles == 0)
10235 // batch debugging code
10236 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10242 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10243 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10246 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10248 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10250 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10251 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);
10258 if (rsurface.batchmultidraw)
10260 // issue multiple draws rather than copying index data
10261 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10262 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10263 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10264 for (i = 0;i < numsurfaces;)
10266 // combine consecutive surfaces as one draw
10267 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10268 if (surfacelist[j] != surfacelist[k] + 1)
10270 firstvertex = surfacelist[i]->num_firstvertex;
10271 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10272 firsttriangle = surfacelist[i]->num_firsttriangle;
10273 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10274 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);
10280 // there is only one consecutive run of index data (may have been combined)
10281 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);
10285 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10287 // pick the closest matching water plane
10288 int planeindex, vertexindex, bestplaneindex = -1;
10292 r_waterstate_waterplane_t *p;
10293 qboolean prepared = false;
10295 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10297 if(p->camera_entity != rsurface.texture->camera_entity)
10302 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10304 if(rsurface.batchnumvertices == 0)
10307 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10309 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10310 d += fabs(PlaneDiff(vert, &p->plane));
10312 if (bestd > d || bestplaneindex < 0)
10315 bestplaneindex = planeindex;
10318 return bestplaneindex;
10319 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10320 // this situation though, as it might be better to render single larger
10321 // batches with useless stuff (backface culled for example) than to
10322 // render multiple smaller batches
10325 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10328 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10329 rsurface.passcolor4f_vertexbuffer = 0;
10330 rsurface.passcolor4f_bufferoffset = 0;
10331 for (i = 0;i < rsurface.batchnumvertices;i++)
10332 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10335 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10342 if (rsurface.passcolor4f)
10344 // generate color arrays
10345 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10346 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10347 rsurface.passcolor4f_vertexbuffer = 0;
10348 rsurface.passcolor4f_bufferoffset = 0;
10349 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)
10351 f = RSurf_FogVertex(v);
10360 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10361 rsurface.passcolor4f_vertexbuffer = 0;
10362 rsurface.passcolor4f_bufferoffset = 0;
10363 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10365 f = RSurf_FogVertex(v);
10374 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10381 if (!rsurface.passcolor4f)
10383 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10384 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10385 rsurface.passcolor4f_vertexbuffer = 0;
10386 rsurface.passcolor4f_bufferoffset = 0;
10387 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)
10389 f = RSurf_FogVertex(v);
10390 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10391 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10392 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10397 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10402 if (!rsurface.passcolor4f)
10404 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10405 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10406 rsurface.passcolor4f_vertexbuffer = 0;
10407 rsurface.passcolor4f_bufferoffset = 0;
10408 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10417 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10422 if (!rsurface.passcolor4f)
10424 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10425 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10426 rsurface.passcolor4f_vertexbuffer = 0;
10427 rsurface.passcolor4f_bufferoffset = 0;
10428 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10430 c2[0] = c[0] + r_refdef.scene.ambient;
10431 c2[1] = c[1] + r_refdef.scene.ambient;
10432 c2[2] = c[2] + r_refdef.scene.ambient;
10437 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10440 rsurface.passcolor4f = NULL;
10441 rsurface.passcolor4f_vertexbuffer = 0;
10442 rsurface.passcolor4f_bufferoffset = 0;
10443 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10444 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10445 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10446 GL_Color(r, g, b, a);
10447 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10448 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10449 R_Mesh_TexMatrix(0, NULL);
10453 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10455 // TODO: optimize applyfog && applycolor case
10456 // just apply fog if necessary, and tint the fog color array if necessary
10457 rsurface.passcolor4f = NULL;
10458 rsurface.passcolor4f_vertexbuffer = 0;
10459 rsurface.passcolor4f_bufferoffset = 0;
10460 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10461 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10462 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10463 GL_Color(r, g, b, a);
10467 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10470 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10471 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10472 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10473 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10474 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10475 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10476 GL_Color(r, g, b, a);
10480 static void RSurf_DrawBatch_GL11_ClampColor(void)
10485 if (!rsurface.passcolor4f)
10487 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10489 c2[0] = bound(0.0f, c1[0], 1.0f);
10490 c2[1] = bound(0.0f, c1[1], 1.0f);
10491 c2[2] = bound(0.0f, c1[2], 1.0f);
10492 c2[3] = bound(0.0f, c1[3], 1.0f);
10496 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10506 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10507 rsurface.passcolor4f_vertexbuffer = 0;
10508 rsurface.passcolor4f_bufferoffset = 0;
10509 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)
10511 f = -DotProduct(r_refdef.view.forward, n);
10513 f = f * 0.85 + 0.15; // work around so stuff won't get black
10514 f *= r_refdef.lightmapintensity;
10515 Vector4Set(c, f, f, f, 1);
10519 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10521 RSurf_DrawBatch_GL11_ApplyFakeLight();
10522 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10523 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10524 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10525 GL_Color(r, g, b, a);
10529 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10537 vec3_t ambientcolor;
10538 vec3_t diffusecolor;
10542 VectorCopy(rsurface.modellight_lightdir, lightdir);
10543 f = 0.5f * r_refdef.lightmapintensity;
10544 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10545 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10546 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10547 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10548 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10549 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10551 if (VectorLength2(diffusecolor) > 0)
10553 // q3-style directional shading
10554 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10555 rsurface.passcolor4f_vertexbuffer = 0;
10556 rsurface.passcolor4f_bufferoffset = 0;
10557 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)
10559 if ((f = DotProduct(n, lightdir)) > 0)
10560 VectorMA(ambientcolor, f, diffusecolor, c);
10562 VectorCopy(ambientcolor, c);
10569 *applycolor = false;
10573 *r = ambientcolor[0];
10574 *g = ambientcolor[1];
10575 *b = ambientcolor[2];
10576 rsurface.passcolor4f = NULL;
10577 rsurface.passcolor4f_vertexbuffer = 0;
10578 rsurface.passcolor4f_bufferoffset = 0;
10582 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10584 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10585 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10586 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10587 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10588 GL_Color(r, g, b, a);
10592 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10600 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10601 rsurface.passcolor4f_vertexbuffer = 0;
10602 rsurface.passcolor4f_bufferoffset = 0;
10604 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10606 f = 1 - RSurf_FogVertex(v);
10614 void RSurf_SetupDepthAndCulling(void)
10616 // submodels are biased to avoid z-fighting with world surfaces that they
10617 // may be exactly overlapping (avoids z-fighting artifacts on certain
10618 // doors and things in Quake maps)
10619 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10620 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10621 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10622 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10625 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10627 // transparent sky would be ridiculous
10628 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10630 R_SetupShader_Generic_NoTexture(false, false);
10631 skyrenderlater = true;
10632 RSurf_SetupDepthAndCulling();
10633 GL_DepthMask(true);
10634 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10635 // skymasking on them, and Quake3 never did sky masking (unlike
10636 // software Quake and software Quake2), so disable the sky masking
10637 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10638 // and skymasking also looks very bad when noclipping outside the
10639 // level, so don't use it then either.
10640 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10642 R_Mesh_ResetTextureState();
10643 if (skyrendermasked)
10645 R_SetupShader_DepthOrShadow(false, false, false);
10646 // depth-only (masking)
10647 GL_ColorMask(0,0,0,0);
10648 // just to make sure that braindead drivers don't draw
10649 // anything despite that colormask...
10650 GL_BlendFunc(GL_ZERO, GL_ONE);
10651 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10652 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10656 R_SetupShader_Generic_NoTexture(false, false);
10658 GL_BlendFunc(GL_ONE, GL_ZERO);
10659 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10660 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10661 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10664 if (skyrendermasked)
10665 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10667 R_Mesh_ResetTextureState();
10668 GL_Color(1, 1, 1, 1);
10671 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10672 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10673 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10675 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10679 // render screenspace normalmap to texture
10680 GL_DepthMask(true);
10681 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10686 // bind lightmap texture
10688 // water/refraction/reflection/camera surfaces have to be handled specially
10689 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10691 int start, end, startplaneindex;
10692 for (start = 0;start < texturenumsurfaces;start = end)
10694 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10695 if(startplaneindex < 0)
10697 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10698 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10702 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10704 // now that we have a batch using the same planeindex, render it
10705 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10707 // render water or distortion background
10708 GL_DepthMask(true);
10709 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);
10711 // blend surface on top
10712 GL_DepthMask(false);
10713 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10716 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10718 // render surface with reflection texture as input
10719 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10720 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);
10727 // render surface batch normally
10728 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10729 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);
10733 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10735 // OpenGL 1.3 path - anything not completely ancient
10736 qboolean applycolor;
10739 const texturelayer_t *layer;
10740 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);
10741 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10743 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10746 int layertexrgbscale;
10747 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10749 if (layerindex == 0)
10750 GL_AlphaTest(true);
10753 GL_AlphaTest(false);
10754 GL_DepthFunc(GL_EQUAL);
10757 GL_DepthMask(layer->depthmask && writedepth);
10758 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10759 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10761 layertexrgbscale = 4;
10762 VectorScale(layer->color, 0.25f, layercolor);
10764 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10766 layertexrgbscale = 2;
10767 VectorScale(layer->color, 0.5f, layercolor);
10771 layertexrgbscale = 1;
10772 VectorScale(layer->color, 1.0f, layercolor);
10774 layercolor[3] = layer->color[3];
10775 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10776 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10777 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10778 switch (layer->type)
10780 case TEXTURELAYERTYPE_LITTEXTURE:
10781 // single-pass lightmapped texture with 2x rgbscale
10782 R_Mesh_TexBind(0, r_texture_white);
10783 R_Mesh_TexMatrix(0, NULL);
10784 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10785 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10786 R_Mesh_TexBind(1, layer->texture);
10787 R_Mesh_TexMatrix(1, &layer->texmatrix);
10788 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10789 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10790 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10791 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10792 else if (FAKELIGHT_ENABLED)
10793 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10794 else if (rsurface.uselightmaptexture)
10795 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10797 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10799 case TEXTURELAYERTYPE_TEXTURE:
10800 // singletexture unlit texture with transparency support
10801 R_Mesh_TexBind(0, layer->texture);
10802 R_Mesh_TexMatrix(0, &layer->texmatrix);
10803 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10804 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10805 R_Mesh_TexBind(1, 0);
10806 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10807 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10809 case TEXTURELAYERTYPE_FOG:
10810 // singletexture fogging
10811 if (layer->texture)
10813 R_Mesh_TexBind(0, layer->texture);
10814 R_Mesh_TexMatrix(0, &layer->texmatrix);
10815 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10816 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10820 R_Mesh_TexBind(0, 0);
10821 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10823 R_Mesh_TexBind(1, 0);
10824 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10825 // generate a color array for the fog pass
10826 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10827 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10831 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10834 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10836 GL_DepthFunc(GL_LEQUAL);
10837 GL_AlphaTest(false);
10841 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10843 // OpenGL 1.1 - crusty old voodoo path
10846 const texturelayer_t *layer;
10847 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);
10848 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10850 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10852 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10854 if (layerindex == 0)
10855 GL_AlphaTest(true);
10858 GL_AlphaTest(false);
10859 GL_DepthFunc(GL_EQUAL);
10862 GL_DepthMask(layer->depthmask && writedepth);
10863 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10864 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10865 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10866 switch (layer->type)
10868 case TEXTURELAYERTYPE_LITTEXTURE:
10869 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10871 // two-pass lit texture with 2x rgbscale
10872 // first the lightmap pass
10873 R_Mesh_TexBind(0, r_texture_white);
10874 R_Mesh_TexMatrix(0, NULL);
10875 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10876 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10877 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10878 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10879 else if (FAKELIGHT_ENABLED)
10880 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10881 else if (rsurface.uselightmaptexture)
10882 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10884 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10885 // then apply the texture to it
10886 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10887 R_Mesh_TexBind(0, layer->texture);
10888 R_Mesh_TexMatrix(0, &layer->texmatrix);
10889 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10890 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10891 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);
10895 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10896 R_Mesh_TexBind(0, layer->texture);
10897 R_Mesh_TexMatrix(0, &layer->texmatrix);
10898 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10899 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10900 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10901 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);
10902 else if (FAKELIGHT_ENABLED)
10903 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);
10905 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);
10908 case TEXTURELAYERTYPE_TEXTURE:
10909 // singletexture unlit texture with transparency support
10910 R_Mesh_TexBind(0, layer->texture);
10911 R_Mesh_TexMatrix(0, &layer->texmatrix);
10912 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10913 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10914 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);
10916 case TEXTURELAYERTYPE_FOG:
10917 // singletexture fogging
10918 if (layer->texture)
10920 R_Mesh_TexBind(0, layer->texture);
10921 R_Mesh_TexMatrix(0, &layer->texmatrix);
10922 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10923 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10927 R_Mesh_TexBind(0, 0);
10928 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10930 // generate a color array for the fog pass
10931 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10932 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10936 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10939 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10941 GL_DepthFunc(GL_LEQUAL);
10942 GL_AlphaTest(false);
10946 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10950 r_vertexgeneric_t *batchvertex;
10953 // R_Mesh_ResetTextureState();
10954 R_SetupShader_Generic_NoTexture(false, false);
10956 if(rsurface.texture && rsurface.texture->currentskinframe)
10958 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10959 c[3] *= rsurface.texture->currentalpha;
10969 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10971 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10972 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10973 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10976 // brighten it up (as texture value 127 means "unlit")
10977 c[0] *= 2 * r_refdef.view.colorscale;
10978 c[1] *= 2 * r_refdef.view.colorscale;
10979 c[2] *= 2 * r_refdef.view.colorscale;
10981 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10982 c[3] *= r_wateralpha.value;
10984 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10986 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10987 GL_DepthMask(false);
10989 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10991 GL_BlendFunc(GL_ONE, GL_ONE);
10992 GL_DepthMask(false);
10994 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10996 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10997 GL_DepthMask(false);
10999 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11001 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11002 GL_DepthMask(false);
11006 GL_BlendFunc(GL_ONE, GL_ZERO);
11007 GL_DepthMask(writedepth);
11010 if (r_showsurfaces.integer == 3)
11012 rsurface.passcolor4f = NULL;
11014 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11016 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11018 rsurface.passcolor4f = NULL;
11019 rsurface.passcolor4f_vertexbuffer = 0;
11020 rsurface.passcolor4f_bufferoffset = 0;
11022 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11024 qboolean applycolor = true;
11027 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11029 r_refdef.lightmapintensity = 1;
11030 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11031 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11033 else if (FAKELIGHT_ENABLED)
11035 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11037 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11038 RSurf_DrawBatch_GL11_ApplyFakeLight();
11039 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11043 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11045 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11046 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11047 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11050 if(!rsurface.passcolor4f)
11051 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11053 RSurf_DrawBatch_GL11_ApplyAmbient();
11054 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11055 if(r_refdef.fogenabled)
11056 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11057 RSurf_DrawBatch_GL11_ClampColor();
11059 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11060 R_SetupShader_Generic_NoTexture(false, false);
11063 else if (!r_refdef.view.showdebug)
11065 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11066 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11067 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11069 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11070 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11072 R_Mesh_PrepareVertices_Generic_Unlock();
11075 else if (r_showsurfaces.integer == 4)
11077 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11078 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11079 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11081 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11082 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11083 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11085 R_Mesh_PrepareVertices_Generic_Unlock();
11088 else if (r_showsurfaces.integer == 2)
11091 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11092 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11093 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11095 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11096 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11097 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11098 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11099 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11100 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11101 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11103 R_Mesh_PrepareVertices_Generic_Unlock();
11104 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11108 int texturesurfaceindex;
11110 const msurface_t *surface;
11111 float surfacecolor4f[4];
11112 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11113 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11115 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11117 surface = texturesurfacelist[texturesurfaceindex];
11118 k = (int)(((size_t)surface) / sizeof(msurface_t));
11119 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11120 for (j = 0;j < surface->num_vertices;j++)
11122 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11123 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11127 R_Mesh_PrepareVertices_Generic_Unlock();
11132 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11135 RSurf_SetupDepthAndCulling();
11136 if (r_showsurfaces.integer)
11138 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11141 switch (vid.renderpath)
11143 case RENDERPATH_GL20:
11144 case RENDERPATH_D3D9:
11145 case RENDERPATH_D3D10:
11146 case RENDERPATH_D3D11:
11147 case RENDERPATH_SOFT:
11148 case RENDERPATH_GLES2:
11149 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11151 case RENDERPATH_GL13:
11152 case RENDERPATH_GLES1:
11153 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11155 case RENDERPATH_GL11:
11156 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11162 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11165 RSurf_SetupDepthAndCulling();
11166 if (r_showsurfaces.integer)
11168 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11171 switch (vid.renderpath)
11173 case RENDERPATH_GL20:
11174 case RENDERPATH_D3D9:
11175 case RENDERPATH_D3D10:
11176 case RENDERPATH_D3D11:
11177 case RENDERPATH_SOFT:
11178 case RENDERPATH_GLES2:
11179 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11181 case RENDERPATH_GL13:
11182 case RENDERPATH_GLES1:
11183 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11185 case RENDERPATH_GL11:
11186 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11192 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11195 int texturenumsurfaces, endsurface;
11196 texture_t *texture;
11197 const msurface_t *surface;
11198 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11200 // if the model is static it doesn't matter what value we give for
11201 // wantnormals and wanttangents, so this logic uses only rules applicable
11202 // to a model, knowing that they are meaningless otherwise
11203 if (ent == r_refdef.scene.worldentity)
11204 RSurf_ActiveWorldEntity();
11205 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11206 RSurf_ActiveModelEntity(ent, false, false, false);
11209 switch (vid.renderpath)
11211 case RENDERPATH_GL20:
11212 case RENDERPATH_D3D9:
11213 case RENDERPATH_D3D10:
11214 case RENDERPATH_D3D11:
11215 case RENDERPATH_SOFT:
11216 case RENDERPATH_GLES2:
11217 RSurf_ActiveModelEntity(ent, true, true, false);
11219 case RENDERPATH_GL11:
11220 case RENDERPATH_GL13:
11221 case RENDERPATH_GLES1:
11222 RSurf_ActiveModelEntity(ent, true, false, false);
11227 if (r_transparentdepthmasking.integer)
11229 qboolean setup = false;
11230 for (i = 0;i < numsurfaces;i = j)
11233 surface = rsurface.modelsurfaces + surfacelist[i];
11234 texture = surface->texture;
11235 rsurface.texture = R_GetCurrentTexture(texture);
11236 rsurface.lightmaptexture = NULL;
11237 rsurface.deluxemaptexture = NULL;
11238 rsurface.uselightmaptexture = false;
11239 // scan ahead until we find a different texture
11240 endsurface = min(i + 1024, numsurfaces);
11241 texturenumsurfaces = 0;
11242 texturesurfacelist[texturenumsurfaces++] = surface;
11243 for (;j < endsurface;j++)
11245 surface = rsurface.modelsurfaces + surfacelist[j];
11246 if (texture != surface->texture)
11248 texturesurfacelist[texturenumsurfaces++] = surface;
11250 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11252 // render the range of surfaces as depth
11256 GL_ColorMask(0,0,0,0);
11258 GL_DepthTest(true);
11259 GL_BlendFunc(GL_ONE, GL_ZERO);
11260 GL_DepthMask(true);
11261 // R_Mesh_ResetTextureState();
11263 RSurf_SetupDepthAndCulling();
11264 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11265 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11266 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11270 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11273 for (i = 0;i < numsurfaces;i = j)
11276 surface = rsurface.modelsurfaces + surfacelist[i];
11277 texture = surface->texture;
11278 rsurface.texture = R_GetCurrentTexture(texture);
11279 // scan ahead until we find a different texture
11280 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11281 texturenumsurfaces = 0;
11282 texturesurfacelist[texturenumsurfaces++] = surface;
11283 if(FAKELIGHT_ENABLED)
11285 rsurface.lightmaptexture = NULL;
11286 rsurface.deluxemaptexture = NULL;
11287 rsurface.uselightmaptexture = false;
11288 for (;j < endsurface;j++)
11290 surface = rsurface.modelsurfaces + surfacelist[j];
11291 if (texture != surface->texture)
11293 texturesurfacelist[texturenumsurfaces++] = surface;
11298 rsurface.lightmaptexture = surface->lightmaptexture;
11299 rsurface.deluxemaptexture = surface->deluxemaptexture;
11300 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11301 for (;j < endsurface;j++)
11303 surface = rsurface.modelsurfaces + surfacelist[j];
11304 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11306 texturesurfacelist[texturenumsurfaces++] = surface;
11309 // render the range of surfaces
11310 if (ent == r_refdef.scene.worldentity)
11311 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11313 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11315 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11318 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11320 // transparent surfaces get pushed off into the transparent queue
11321 int surfacelistindex;
11322 const msurface_t *surface;
11323 vec3_t tempcenter, center;
11324 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11326 surface = texturesurfacelist[surfacelistindex];
11327 if (r_transparent_sortsurfacesbynearest.integer)
11329 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11330 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11331 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11335 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11336 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11337 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11339 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11340 if (rsurface.entity->transparent_offset) // transparent offset
11342 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11343 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11344 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11346 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);
11350 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11352 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11354 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11356 RSurf_SetupDepthAndCulling();
11357 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11358 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11359 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11363 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11367 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11370 if (!rsurface.texture->currentnumlayers)
11372 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11373 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11375 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11377 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11378 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11379 else if (!rsurface.texture->currentnumlayers)
11381 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11383 // in the deferred case, transparent surfaces were queued during prepass
11384 if (!r_shadow_usingdeferredprepass)
11385 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11389 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11390 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11395 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11398 texture_t *texture;
11399 R_FrameData_SetMark();
11400 // break the surface list down into batches by texture and use of lightmapping
11401 for (i = 0;i < numsurfaces;i = j)
11404 // texture is the base texture pointer, rsurface.texture is the
11405 // current frame/skin the texture is directing us to use (for example
11406 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11407 // use skin 1 instead)
11408 texture = surfacelist[i]->texture;
11409 rsurface.texture = R_GetCurrentTexture(texture);
11410 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11412 // if this texture is not the kind we want, skip ahead to the next one
11413 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11417 if(FAKELIGHT_ENABLED || depthonly || prepass)
11419 rsurface.lightmaptexture = NULL;
11420 rsurface.deluxemaptexture = NULL;
11421 rsurface.uselightmaptexture = false;
11422 // simply scan ahead until we find a different texture or lightmap state
11423 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11428 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11429 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11430 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11431 // simply scan ahead until we find a different texture or lightmap state
11432 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11435 // render the range of surfaces
11436 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11438 R_FrameData_ReturnToMark();
11441 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11445 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11448 if (!rsurface.texture->currentnumlayers)
11450 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11451 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11453 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11455 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11456 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11457 else if (!rsurface.texture->currentnumlayers)
11459 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11461 // in the deferred case, transparent surfaces were queued during prepass
11462 if (!r_shadow_usingdeferredprepass)
11463 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11467 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11468 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11473 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11476 texture_t *texture;
11477 R_FrameData_SetMark();
11478 // break the surface list down into batches by texture and use of lightmapping
11479 for (i = 0;i < numsurfaces;i = j)
11482 // texture is the base texture pointer, rsurface.texture is the
11483 // current frame/skin the texture is directing us to use (for example
11484 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11485 // use skin 1 instead)
11486 texture = surfacelist[i]->texture;
11487 rsurface.texture = R_GetCurrentTexture(texture);
11488 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11490 // if this texture is not the kind we want, skip ahead to the next one
11491 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11495 if(FAKELIGHT_ENABLED || depthonly || prepass)
11497 rsurface.lightmaptexture = NULL;
11498 rsurface.deluxemaptexture = NULL;
11499 rsurface.uselightmaptexture = false;
11500 // simply scan ahead until we find a different texture or lightmap state
11501 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11506 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11507 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11508 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11509 // simply scan ahead until we find a different texture or lightmap state
11510 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11513 // render the range of surfaces
11514 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11516 R_FrameData_ReturnToMark();
11519 float locboxvertex3f[6*4*3] =
11521 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11522 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11523 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11524 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11525 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11526 1,0,0, 0,0,0, 0,1,0, 1,1,0
11529 unsigned short locboxelements[6*2*3] =
11534 12,13,14, 12,14,15,
11535 16,17,18, 16,18,19,
11539 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11542 cl_locnode_t *loc = (cl_locnode_t *)ent;
11544 float vertex3f[6*4*3];
11546 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11547 GL_DepthMask(false);
11548 GL_DepthRange(0, 1);
11549 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11550 GL_DepthTest(true);
11551 GL_CullFace(GL_NONE);
11552 R_EntityMatrix(&identitymatrix);
11554 // R_Mesh_ResetTextureState();
11556 i = surfacelist[0];
11557 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11558 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11559 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11560 surfacelist[0] < 0 ? 0.5f : 0.125f);
11562 if (VectorCompare(loc->mins, loc->maxs))
11564 VectorSet(size, 2, 2, 2);
11565 VectorMA(loc->mins, -0.5f, size, mins);
11569 VectorCopy(loc->mins, mins);
11570 VectorSubtract(loc->maxs, loc->mins, size);
11573 for (i = 0;i < 6*4*3;)
11574 for (j = 0;j < 3;j++, i++)
11575 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11577 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11578 R_SetupShader_Generic_NoTexture(false, false);
11579 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11582 void R_DrawLocs(void)
11585 cl_locnode_t *loc, *nearestloc;
11587 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11588 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11590 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11591 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11595 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11597 if (decalsystem->decals)
11598 Mem_Free(decalsystem->decals);
11599 memset(decalsystem, 0, sizeof(*decalsystem));
11602 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)
11605 tridecal_t *decals;
11608 // expand or initialize the system
11609 if (decalsystem->maxdecals <= decalsystem->numdecals)
11611 decalsystem_t old = *decalsystem;
11612 qboolean useshortelements;
11613 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11614 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11615 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)));
11616 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11617 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11618 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11619 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11620 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11621 if (decalsystem->numdecals)
11622 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11624 Mem_Free(old.decals);
11625 for (i = 0;i < decalsystem->maxdecals*3;i++)
11626 decalsystem->element3i[i] = i;
11627 if (useshortelements)
11628 for (i = 0;i < decalsystem->maxdecals*3;i++)
11629 decalsystem->element3s[i] = i;
11632 // grab a decal and search for another free slot for the next one
11633 decals = decalsystem->decals;
11634 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11635 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11637 decalsystem->freedecal = i;
11638 if (decalsystem->numdecals <= i)
11639 decalsystem->numdecals = i + 1;
11641 // initialize the decal
11643 decal->triangleindex = triangleindex;
11644 decal->surfaceindex = surfaceindex;
11645 decal->decalsequence = decalsequence;
11646 decal->color4f[0][0] = c0[0];
11647 decal->color4f[0][1] = c0[1];
11648 decal->color4f[0][2] = c0[2];
11649 decal->color4f[0][3] = 1;
11650 decal->color4f[1][0] = c1[0];
11651 decal->color4f[1][1] = c1[1];
11652 decal->color4f[1][2] = c1[2];
11653 decal->color4f[1][3] = 1;
11654 decal->color4f[2][0] = c2[0];
11655 decal->color4f[2][1] = c2[1];
11656 decal->color4f[2][2] = c2[2];
11657 decal->color4f[2][3] = 1;
11658 decal->vertex3f[0][0] = v0[0];
11659 decal->vertex3f[0][1] = v0[1];
11660 decal->vertex3f[0][2] = v0[2];
11661 decal->vertex3f[1][0] = v1[0];
11662 decal->vertex3f[1][1] = v1[1];
11663 decal->vertex3f[1][2] = v1[2];
11664 decal->vertex3f[2][0] = v2[0];
11665 decal->vertex3f[2][1] = v2[1];
11666 decal->vertex3f[2][2] = v2[2];
11667 decal->texcoord2f[0][0] = t0[0];
11668 decal->texcoord2f[0][1] = t0[1];
11669 decal->texcoord2f[1][0] = t1[0];
11670 decal->texcoord2f[1][1] = t1[1];
11671 decal->texcoord2f[2][0] = t2[0];
11672 decal->texcoord2f[2][1] = t2[1];
11673 TriangleNormal(v0, v1, v2, decal->plane);
11674 VectorNormalize(decal->plane);
11675 decal->plane[3] = DotProduct(v0, decal->plane);
11678 extern cvar_t cl_decals_bias;
11679 extern cvar_t cl_decals_models;
11680 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11681 // baseparms, parms, temps
11682 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)
11687 const float *vertex3f;
11688 const float *normal3f;
11690 float points[2][9][3];
11697 e = rsurface.modelelement3i + 3*triangleindex;
11699 vertex3f = rsurface.modelvertex3f;
11700 normal3f = rsurface.modelnormal3f;
11704 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11706 index = 3*e[cornerindex];
11707 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11712 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11714 index = 3*e[cornerindex];
11715 VectorCopy(vertex3f + index, v[cornerindex]);
11720 //TriangleNormal(v[0], v[1], v[2], normal);
11721 //if (DotProduct(normal, localnormal) < 0.0f)
11723 // clip by each of the box planes formed from the projection matrix
11724 // if anything survives, we emit the decal
11725 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]);
11728 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]);
11731 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]);
11734 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]);
11737 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]);
11740 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]);
11743 // some part of the triangle survived, so we have to accept it...
11746 // dynamic always uses the original triangle
11748 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11750 index = 3*e[cornerindex];
11751 VectorCopy(vertex3f + index, v[cornerindex]);
11754 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11756 // convert vertex positions to texcoords
11757 Matrix4x4_Transform(projection, v[cornerindex], temp);
11758 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11759 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11760 // calculate distance fade from the projection origin
11761 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11762 f = bound(0.0f, f, 1.0f);
11763 c[cornerindex][0] = r * f;
11764 c[cornerindex][1] = g * f;
11765 c[cornerindex][2] = b * f;
11766 c[cornerindex][3] = 1.0f;
11767 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11770 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);
11772 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11773 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);
11775 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)
11777 matrix4x4_t projection;
11778 decalsystem_t *decalsystem;
11781 const msurface_t *surface;
11782 const msurface_t *surfaces;
11783 const int *surfacelist;
11784 const texture_t *texture;
11786 int numsurfacelist;
11787 int surfacelistindex;
11790 float localorigin[3];
11791 float localnormal[3];
11792 float localmins[3];
11793 float localmaxs[3];
11796 float planes[6][4];
11799 int bih_triangles_count;
11800 int bih_triangles[256];
11801 int bih_surfaces[256];
11803 decalsystem = &ent->decalsystem;
11804 model = ent->model;
11805 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11807 R_DecalSystem_Reset(&ent->decalsystem);
11811 if (!model->brush.data_leafs && !cl_decals_models.integer)
11813 if (decalsystem->model)
11814 R_DecalSystem_Reset(decalsystem);
11818 if (decalsystem->model != model)
11819 R_DecalSystem_Reset(decalsystem);
11820 decalsystem->model = model;
11822 RSurf_ActiveModelEntity(ent, true, false, false);
11824 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11825 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11826 VectorNormalize(localnormal);
11827 localsize = worldsize*rsurface.inversematrixscale;
11828 localmins[0] = localorigin[0] - localsize;
11829 localmins[1] = localorigin[1] - localsize;
11830 localmins[2] = localorigin[2] - localsize;
11831 localmaxs[0] = localorigin[0] + localsize;
11832 localmaxs[1] = localorigin[1] + localsize;
11833 localmaxs[2] = localorigin[2] + localsize;
11835 //VectorCopy(localnormal, planes[4]);
11836 //VectorVectors(planes[4], planes[2], planes[0]);
11837 AnglesFromVectors(angles, localnormal, NULL, false);
11838 AngleVectors(angles, planes[0], planes[2], planes[4]);
11839 VectorNegate(planes[0], planes[1]);
11840 VectorNegate(planes[2], planes[3]);
11841 VectorNegate(planes[4], planes[5]);
11842 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11843 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11844 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11845 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11846 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11847 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11852 matrix4x4_t forwardprojection;
11853 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11854 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11859 float projectionvector[4][3];
11860 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11861 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11862 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11863 projectionvector[0][0] = planes[0][0] * ilocalsize;
11864 projectionvector[0][1] = planes[1][0] * ilocalsize;
11865 projectionvector[0][2] = planes[2][0] * ilocalsize;
11866 projectionvector[1][0] = planes[0][1] * ilocalsize;
11867 projectionvector[1][1] = planes[1][1] * ilocalsize;
11868 projectionvector[1][2] = planes[2][1] * ilocalsize;
11869 projectionvector[2][0] = planes[0][2] * ilocalsize;
11870 projectionvector[2][1] = planes[1][2] * ilocalsize;
11871 projectionvector[2][2] = planes[2][2] * ilocalsize;
11872 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11873 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11874 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11875 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11879 dynamic = model->surfmesh.isanimated;
11880 numsurfacelist = model->nummodelsurfaces;
11881 surfacelist = model->sortedmodelsurfaces;
11882 surfaces = model->data_surfaces;
11885 bih_triangles_count = -1;
11888 if(model->render_bih.numleafs)
11889 bih = &model->render_bih;
11890 else if(model->collision_bih.numleafs)
11891 bih = &model->collision_bih;
11894 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11895 if(bih_triangles_count == 0)
11897 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11899 if(bih_triangles_count > 0)
11901 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11903 surfaceindex = bih_surfaces[triangleindex];
11904 surface = surfaces + surfaceindex;
11905 texture = surface->texture;
11906 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11908 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11910 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11915 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11917 surfaceindex = surfacelist[surfacelistindex];
11918 surface = surfaces + surfaceindex;
11919 // check cull box first because it rejects more than any other check
11920 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11922 // skip transparent surfaces
11923 texture = surface->texture;
11924 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11926 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11928 numtriangles = surface->num_triangles;
11929 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11930 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11935 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11936 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)
11938 int renderentityindex;
11939 float worldmins[3];
11940 float worldmaxs[3];
11941 entity_render_t *ent;
11943 if (!cl_decals_newsystem.integer)
11946 worldmins[0] = worldorigin[0] - worldsize;
11947 worldmins[1] = worldorigin[1] - worldsize;
11948 worldmins[2] = worldorigin[2] - worldsize;
11949 worldmaxs[0] = worldorigin[0] + worldsize;
11950 worldmaxs[1] = worldorigin[1] + worldsize;
11951 worldmaxs[2] = worldorigin[2] + worldsize;
11953 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11955 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11957 ent = r_refdef.scene.entities[renderentityindex];
11958 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11961 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11965 typedef struct r_decalsystem_splatqueue_s
11967 vec3_t worldorigin;
11968 vec3_t worldnormal;
11974 r_decalsystem_splatqueue_t;
11976 int r_decalsystem_numqueued = 0;
11977 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11979 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)
11981 r_decalsystem_splatqueue_t *queue;
11983 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11986 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11987 VectorCopy(worldorigin, queue->worldorigin);
11988 VectorCopy(worldnormal, queue->worldnormal);
11989 Vector4Set(queue->color, r, g, b, a);
11990 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11991 queue->worldsize = worldsize;
11992 queue->decalsequence = cl.decalsequence++;
11995 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11998 r_decalsystem_splatqueue_t *queue;
12000 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12001 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);
12002 r_decalsystem_numqueued = 0;
12005 extern cvar_t cl_decals_max;
12006 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12009 decalsystem_t *decalsystem = &ent->decalsystem;
12016 if (!decalsystem->numdecals)
12019 if (r_showsurfaces.integer)
12022 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12024 R_DecalSystem_Reset(decalsystem);
12028 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12029 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12031 if (decalsystem->lastupdatetime)
12032 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12035 decalsystem->lastupdatetime = r_refdef.scene.time;
12036 numdecals = decalsystem->numdecals;
12038 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12040 if (decal->color4f[0][3])
12042 decal->lived += frametime;
12043 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12045 memset(decal, 0, sizeof(*decal));
12046 if (decalsystem->freedecal > i)
12047 decalsystem->freedecal = i;
12051 decal = decalsystem->decals;
12052 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12055 // collapse the array by shuffling the tail decals into the gaps
12058 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12059 decalsystem->freedecal++;
12060 if (decalsystem->freedecal == numdecals)
12062 decal[decalsystem->freedecal] = decal[--numdecals];
12065 decalsystem->numdecals = numdecals;
12067 if (numdecals <= 0)
12069 // if there are no decals left, reset decalsystem
12070 R_DecalSystem_Reset(decalsystem);
12074 extern skinframe_t *decalskinframe;
12075 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12078 decalsystem_t *decalsystem = &ent->decalsystem;
12087 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12090 numdecals = decalsystem->numdecals;
12094 if (r_showsurfaces.integer)
12097 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12099 R_DecalSystem_Reset(decalsystem);
12103 // if the model is static it doesn't matter what value we give for
12104 // wantnormals and wanttangents, so this logic uses only rules applicable
12105 // to a model, knowing that they are meaningless otherwise
12106 if (ent == r_refdef.scene.worldentity)
12107 RSurf_ActiveWorldEntity();
12109 RSurf_ActiveModelEntity(ent, false, false, false);
12111 decalsystem->lastupdatetime = r_refdef.scene.time;
12113 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12115 // update vertex positions for animated models
12116 v3f = decalsystem->vertex3f;
12117 c4f = decalsystem->color4f;
12118 t2f = decalsystem->texcoord2f;
12119 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12121 if (!decal->color4f[0][3])
12124 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12128 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12131 // update color values for fading decals
12132 if (decal->lived >= cl_decals_time.value)
12133 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12137 c4f[ 0] = decal->color4f[0][0] * alpha;
12138 c4f[ 1] = decal->color4f[0][1] * alpha;
12139 c4f[ 2] = decal->color4f[0][2] * alpha;
12141 c4f[ 4] = decal->color4f[1][0] * alpha;
12142 c4f[ 5] = decal->color4f[1][1] * alpha;
12143 c4f[ 6] = decal->color4f[1][2] * alpha;
12145 c4f[ 8] = decal->color4f[2][0] * alpha;
12146 c4f[ 9] = decal->color4f[2][1] * alpha;
12147 c4f[10] = decal->color4f[2][2] * alpha;
12150 t2f[0] = decal->texcoord2f[0][0];
12151 t2f[1] = decal->texcoord2f[0][1];
12152 t2f[2] = decal->texcoord2f[1][0];
12153 t2f[3] = decal->texcoord2f[1][1];
12154 t2f[4] = decal->texcoord2f[2][0];
12155 t2f[5] = decal->texcoord2f[2][1];
12157 // update vertex positions for animated models
12158 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12160 e = rsurface.modelelement3i + 3*decal->triangleindex;
12161 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12162 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12163 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12167 VectorCopy(decal->vertex3f[0], v3f);
12168 VectorCopy(decal->vertex3f[1], v3f + 3);
12169 VectorCopy(decal->vertex3f[2], v3f + 6);
12172 if (r_refdef.fogenabled)
12174 alpha = RSurf_FogVertex(v3f);
12175 VectorScale(c4f, alpha, c4f);
12176 alpha = RSurf_FogVertex(v3f + 3);
12177 VectorScale(c4f + 4, alpha, c4f + 4);
12178 alpha = RSurf_FogVertex(v3f + 6);
12179 VectorScale(c4f + 8, alpha, c4f + 8);
12190 r_refdef.stats[r_stat_drawndecals] += numtris;
12192 // now render the decals all at once
12193 // (this assumes they all use one particle font texture!)
12194 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);
12195 // R_Mesh_ResetTextureState();
12196 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12197 GL_DepthMask(false);
12198 GL_DepthRange(0, 1);
12199 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12200 GL_DepthTest(true);
12201 GL_CullFace(GL_NONE);
12202 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12203 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12204 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12208 static void R_DrawModelDecals(void)
12212 // fade faster when there are too many decals
12213 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12214 for (i = 0;i < r_refdef.scene.numentities;i++)
12215 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12217 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12218 for (i = 0;i < r_refdef.scene.numentities;i++)
12219 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12220 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12222 R_DecalSystem_ApplySplatEntitiesQueue();
12224 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12225 for (i = 0;i < r_refdef.scene.numentities;i++)
12226 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12228 r_refdef.stats[r_stat_totaldecals] += numdecals;
12230 if (r_showsurfaces.integer)
12233 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12235 for (i = 0;i < r_refdef.scene.numentities;i++)
12237 if (!r_refdef.viewcache.entityvisible[i])
12239 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12240 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12244 extern cvar_t mod_collision_bih;
12245 static void R_DrawDebugModel(void)
12247 entity_render_t *ent = rsurface.entity;
12248 int i, j, flagsmask;
12249 const msurface_t *surface;
12250 dp_model_t *model = ent->model;
12252 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12255 if (r_showoverdraw.value > 0)
12257 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12258 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12259 R_SetupShader_Generic_NoTexture(false, false);
12260 GL_DepthTest(false);
12261 GL_DepthMask(false);
12262 GL_DepthRange(0, 1);
12263 GL_BlendFunc(GL_ONE, GL_ONE);
12264 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12266 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12268 rsurface.texture = R_GetCurrentTexture(surface->texture);
12269 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12271 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12272 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12273 if (!rsurface.texture->currentlayers->depthmask)
12274 GL_Color(c, 0, 0, 1.0f);
12275 else if (ent == r_refdef.scene.worldentity)
12276 GL_Color(c, c, c, 1.0f);
12278 GL_Color(0, c, 0, 1.0f);
12279 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12283 rsurface.texture = NULL;
12286 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12288 // R_Mesh_ResetTextureState();
12289 R_SetupShader_Generic_NoTexture(false, false);
12290 GL_DepthRange(0, 1);
12291 GL_DepthTest(!r_showdisabledepthtest.integer);
12292 GL_DepthMask(false);
12293 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12295 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12299 qboolean cullbox = false;
12300 const q3mbrush_t *brush;
12301 const bih_t *bih = &model->collision_bih;
12302 const bih_leaf_t *bihleaf;
12303 float vertex3f[3][3];
12304 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12305 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12307 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12309 switch (bihleaf->type)
12312 brush = model->brush.data_brushes + bihleaf->itemindex;
12313 if (brush->colbrushf && brush->colbrushf->numtriangles)
12315 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);
12316 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12317 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12320 case BIH_COLLISIONTRIANGLE:
12321 triangleindex = bihleaf->itemindex;
12322 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12323 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12324 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12325 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12326 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12327 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12329 case BIH_RENDERTRIANGLE:
12330 triangleindex = bihleaf->itemindex;
12331 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12332 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12333 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12334 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);
12335 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12336 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12342 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12345 if (r_showtris.integer && qglPolygonMode)
12347 if (r_showdisabledepthtest.integer)
12349 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12350 GL_DepthMask(false);
12354 GL_BlendFunc(GL_ONE, GL_ZERO);
12355 GL_DepthMask(true);
12357 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12358 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12360 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12362 rsurface.texture = R_GetCurrentTexture(surface->texture);
12363 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12365 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12366 if (!rsurface.texture->currentlayers->depthmask)
12367 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12368 else if (ent == r_refdef.scene.worldentity)
12369 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12371 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12372 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12376 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12377 rsurface.texture = NULL;
12380 if (r_shownormals.value != 0 && qglBegin)
12384 if (r_showdisabledepthtest.integer)
12386 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12387 GL_DepthMask(false);
12391 GL_BlendFunc(GL_ONE, GL_ZERO);
12392 GL_DepthMask(true);
12394 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12396 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12398 rsurface.texture = R_GetCurrentTexture(surface->texture);
12399 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12401 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12402 qglBegin(GL_LINES);
12403 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12405 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12407 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12408 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12409 qglVertex3f(v[0], v[1], v[2]);
12410 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12411 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12412 qglVertex3f(v[0], v[1], v[2]);
12415 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12417 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12419 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12420 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12421 qglVertex3f(v[0], v[1], v[2]);
12422 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12423 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12424 qglVertex3f(v[0], v[1], v[2]);
12427 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12429 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12431 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12432 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12433 qglVertex3f(v[0], v[1], v[2]);
12434 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12435 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12436 qglVertex3f(v[0], v[1], v[2]);
12439 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12441 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12443 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12444 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12445 qglVertex3f(v[0], v[1], v[2]);
12446 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12447 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12448 qglVertex3f(v[0], v[1], v[2]);
12455 rsurface.texture = NULL;
12460 int r_maxsurfacelist = 0;
12461 const msurface_t **r_surfacelist = NULL;
12462 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12464 int i, j, endj, flagsmask;
12465 dp_model_t *model = r_refdef.scene.worldmodel;
12466 msurface_t *surfaces;
12467 unsigned char *update;
12468 int numsurfacelist = 0;
12472 if (r_maxsurfacelist < model->num_surfaces)
12474 r_maxsurfacelist = model->num_surfaces;
12476 Mem_Free((msurface_t**)r_surfacelist);
12477 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12480 RSurf_ActiveWorldEntity();
12482 surfaces = model->data_surfaces;
12483 update = model->brushq1.lightmapupdateflags;
12485 // update light styles on this submodel
12486 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12488 model_brush_lightstyleinfo_t *style;
12489 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12491 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12493 int *list = style->surfacelist;
12494 style->value = r_refdef.scene.lightstylevalue[style->style];
12495 for (j = 0;j < style->numsurfaces;j++)
12496 update[list[j]] = true;
12501 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12505 R_DrawDebugModel();
12506 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12510 rsurface.lightmaptexture = NULL;
12511 rsurface.deluxemaptexture = NULL;
12512 rsurface.uselightmaptexture = false;
12513 rsurface.texture = NULL;
12514 rsurface.rtlight = NULL;
12515 numsurfacelist = 0;
12516 // add visible surfaces to draw list
12517 for (i = 0;i < model->nummodelsurfaces;i++)
12519 j = model->sortedmodelsurfaces[i];
12520 if (r_refdef.viewcache.world_surfacevisible[j])
12521 r_surfacelist[numsurfacelist++] = surfaces + j;
12523 // update lightmaps if needed
12524 if (model->brushq1.firstrender)
12526 model->brushq1.firstrender = false;
12527 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12529 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12533 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12534 if (r_refdef.viewcache.world_surfacevisible[j])
12536 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12538 // don't do anything if there were no surfaces
12539 if (!numsurfacelist)
12541 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12544 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12546 // add to stats if desired
12547 if (r_speeds.integer && !skysurfaces && !depthonly)
12549 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12550 for (j = 0;j < numsurfacelist;j++)
12551 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12554 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12557 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12559 int i, j, endj, flagsmask;
12560 dp_model_t *model = ent->model;
12561 msurface_t *surfaces;
12562 unsigned char *update;
12563 int numsurfacelist = 0;
12567 if (r_maxsurfacelist < model->num_surfaces)
12569 r_maxsurfacelist = model->num_surfaces;
12571 Mem_Free((msurface_t **)r_surfacelist);
12572 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12575 // if the model is static it doesn't matter what value we give for
12576 // wantnormals and wanttangents, so this logic uses only rules applicable
12577 // to a model, knowing that they are meaningless otherwise
12578 if (ent == r_refdef.scene.worldentity)
12579 RSurf_ActiveWorldEntity();
12580 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12581 RSurf_ActiveModelEntity(ent, false, false, false);
12583 RSurf_ActiveModelEntity(ent, true, true, true);
12584 else if (depthonly)
12586 switch (vid.renderpath)
12588 case RENDERPATH_GL20:
12589 case RENDERPATH_D3D9:
12590 case RENDERPATH_D3D10:
12591 case RENDERPATH_D3D11:
12592 case RENDERPATH_SOFT:
12593 case RENDERPATH_GLES2:
12594 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12596 case RENDERPATH_GL11:
12597 case RENDERPATH_GL13:
12598 case RENDERPATH_GLES1:
12599 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12605 switch (vid.renderpath)
12607 case RENDERPATH_GL20:
12608 case RENDERPATH_D3D9:
12609 case RENDERPATH_D3D10:
12610 case RENDERPATH_D3D11:
12611 case RENDERPATH_SOFT:
12612 case RENDERPATH_GLES2:
12613 RSurf_ActiveModelEntity(ent, true, true, false);
12615 case RENDERPATH_GL11:
12616 case RENDERPATH_GL13:
12617 case RENDERPATH_GLES1:
12618 RSurf_ActiveModelEntity(ent, true, false, false);
12623 surfaces = model->data_surfaces;
12624 update = model->brushq1.lightmapupdateflags;
12626 // update light styles
12627 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12629 model_brush_lightstyleinfo_t *style;
12630 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12632 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12634 int *list = style->surfacelist;
12635 style->value = r_refdef.scene.lightstylevalue[style->style];
12636 for (j = 0;j < style->numsurfaces;j++)
12637 update[list[j]] = true;
12642 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12646 R_DrawDebugModel();
12647 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12651 rsurface.lightmaptexture = NULL;
12652 rsurface.deluxemaptexture = NULL;
12653 rsurface.uselightmaptexture = false;
12654 rsurface.texture = NULL;
12655 rsurface.rtlight = NULL;
12656 numsurfacelist = 0;
12657 // add visible surfaces to draw list
12658 for (i = 0;i < model->nummodelsurfaces;i++)
12659 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12660 // don't do anything if there were no surfaces
12661 if (!numsurfacelist)
12663 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12666 // update lightmaps if needed
12670 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12675 R_BuildLightMap(ent, surfaces + j);
12680 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12682 // add to stats if desired
12683 if (r_speeds.integer && !skysurfaces && !depthonly)
12685 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12686 for (j = 0;j < numsurfacelist;j++)
12687 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12690 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12693 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12695 static texture_t texture;
12696 static msurface_t surface;
12697 const msurface_t *surfacelist = &surface;
12699 // fake enough texture and surface state to render this geometry
12701 texture.update_lastrenderframe = -1; // regenerate this texture
12702 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12703 texture.currentskinframe = skinframe;
12704 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12705 texture.offsetmapping = OFFSETMAPPING_OFF;
12706 texture.offsetscale = 1;
12707 texture.specularscalemod = 1;
12708 texture.specularpowermod = 1;
12709 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12710 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12711 // JUST GREP FOR "specularscalemod = 1".
12713 surface.texture = &texture;
12714 surface.num_triangles = numtriangles;
12715 surface.num_firsttriangle = firsttriangle;
12716 surface.num_vertices = numvertices;
12717 surface.num_firstvertex = firstvertex;
12720 rsurface.texture = R_GetCurrentTexture(surface.texture);
12721 rsurface.lightmaptexture = NULL;
12722 rsurface.deluxemaptexture = NULL;
12723 rsurface.uselightmaptexture = false;
12724 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12727 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)
12729 static msurface_t surface;
12730 const msurface_t *surfacelist = &surface;
12732 // fake enough texture and surface state to render this geometry
12733 surface.texture = texture;
12734 surface.num_triangles = numtriangles;
12735 surface.num_firsttriangle = firsttriangle;
12736 surface.num_vertices = numvertices;
12737 surface.num_firstvertex = firstvertex;
12740 rsurface.texture = R_GetCurrentTexture(surface.texture);
12741 rsurface.lightmaptexture = NULL;
12742 rsurface.deluxemaptexture = NULL;
12743 rsurface.uselightmaptexture = false;
12744 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);