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)
884 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
886 #define SHADERSTATICPARMS_COUNT 14
888 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
889 static int shaderstaticparms_count = 0;
891 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
892 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
894 extern qboolean r_shadow_shadowmapsampler;
895 extern int r_shadow_shadowmappcf;
896 qboolean R_CompileShader_CheckStaticParms(void)
898 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
899 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
900 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
903 if (r_glsl_saturation_redcompensate.integer)
904 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
905 if (r_glsl_vertextextureblend_usebothalphas.integer)
906 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
907 if (r_shadow_glossexact.integer)
908 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
909 if (r_glsl_postprocess.integer)
911 if (r_glsl_postprocess_uservec1_enable.integer)
912 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
913 if (r_glsl_postprocess_uservec2_enable.integer)
914 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
915 if (r_glsl_postprocess_uservec3_enable.integer)
916 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
917 if (r_glsl_postprocess_uservec4_enable.integer)
918 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
921 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
922 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
923 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
925 if (r_shadow_shadowmapsampler)
926 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
927 if (r_shadow_shadowmappcf > 1)
928 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
929 else if (r_shadow_shadowmappcf)
930 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
931 if (r_celshading.integer)
932 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
933 if (r_celoutlines.integer)
934 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
936 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
939 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
940 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
941 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
943 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
944 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
946 shaderstaticparms_count = 0;
949 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
950 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
951 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
952 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
953 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
954 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
955 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
956 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
957 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
958 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
959 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
960 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
961 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
962 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
965 /// information about each possible shader permutation
966 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
967 /// currently selected permutation
968 r_glsl_permutation_t *r_glsl_permutation;
969 /// storage for permutations linked in the hash table
970 memexpandablearray_t r_glsl_permutationarray;
972 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
974 //unsigned int hashdepth = 0;
975 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
976 r_glsl_permutation_t *p;
977 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
979 if (p->mode == mode && p->permutation == permutation)
981 //if (hashdepth > 10)
982 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
987 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
989 p->permutation = permutation;
990 p->hashnext = r_glsl_permutationhash[mode][hashindex];
991 r_glsl_permutationhash[mode][hashindex] = p;
992 //if (hashdepth > 10)
993 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
997 static char *R_ShaderStrCat(const char **strings)
1000 const char **p = strings;
1003 for (p = strings;(t = *p);p++)
1006 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1008 for (p = strings;(t = *p);p++)
1018 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1021 if (!filename || !filename[0])
1023 // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1024 if (!strcmp(filename, "glsl/default.glsl"))
1027 return R_ShaderStrCat(builtinshaderstrings);
1028 if (!glslshaderstring)
1030 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1031 if (glslshaderstring)
1032 Con_DPrintf("Loading shaders from file %s...\n", filename);
1034 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1036 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1037 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1038 return shaderstring;
1040 if (!strcmp(filename, "hlsl/default.hlsl"))
1043 return R_ShaderStrCat(builtinhlslshaderstrings);
1044 if (!hlslshaderstring)
1046 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1047 if (hlslshaderstring)
1048 Con_DPrintf("Loading shaders from file %s...\n", filename);
1050 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1052 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1053 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1054 return shaderstring;
1056 // we don't have builtin strings for any other files
1059 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1062 if (printfromdisknotice)
1063 Con_DPrintf("from disk %s... ", filename);
1064 return shaderstring;
1066 return shaderstring;
1069 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1074 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1076 char permutationname[256];
1077 int vertstrings_count = 0;
1078 int geomstrings_count = 0;
1079 int fragstrings_count = 0;
1080 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1081 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1082 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1089 permutationname[0] = 0;
1090 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1092 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1094 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1095 if(vid.support.glshaderversion >= 140)
1097 vertstrings_list[vertstrings_count++] = "#version 140\n";
1098 geomstrings_list[geomstrings_count++] = "#version 140\n";
1099 fragstrings_list[fragstrings_count++] = "#version 140\n";
1100 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1101 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1102 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1104 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1105 else if(vid.support.glshaderversion >= 130)
1107 vertstrings_list[vertstrings_count++] = "#version 130\n";
1108 geomstrings_list[geomstrings_count++] = "#version 130\n";
1109 fragstrings_list[fragstrings_count++] = "#version 130\n";
1110 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1111 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1112 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1115 // the first pretext is which type of shader to compile as
1116 // (later these will all be bound together as a program object)
1117 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1118 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1119 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1121 // the second pretext is the mode (for example a light source)
1122 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1123 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1124 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1125 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1127 // now add all the permutation pretexts
1128 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1130 if (permutation & (1<<i))
1132 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1133 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1134 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1135 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1139 // keep line numbers correct
1140 vertstrings_list[vertstrings_count++] = "\n";
1141 geomstrings_list[geomstrings_count++] = "\n";
1142 fragstrings_list[fragstrings_count++] = "\n";
1147 R_CompileShader_AddStaticParms(mode, permutation);
1148 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1149 vertstrings_count += shaderstaticparms_count;
1150 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1151 geomstrings_count += shaderstaticparms_count;
1152 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1153 fragstrings_count += shaderstaticparms_count;
1155 // now append the shader text itself
1156 vertstrings_list[vertstrings_count++] = sourcestring;
1157 geomstrings_list[geomstrings_count++] = sourcestring;
1158 fragstrings_list[fragstrings_count++] = sourcestring;
1160 // compile the shader program
1161 if (vertstrings_count + geomstrings_count + fragstrings_count)
1162 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1166 qglUseProgram(p->program);CHECKGLERROR
1167 // look up all the uniform variable names we care about, so we don't
1168 // have to look them up every time we set them
1173 GLint activeuniformindex = 0;
1174 GLint numactiveuniforms = 0;
1175 char uniformname[128];
1176 GLsizei uniformnamelength = 0;
1177 GLint uniformsize = 0;
1178 GLenum uniformtype = 0;
1179 memset(uniformname, 0, sizeof(uniformname));
1180 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1181 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1182 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1184 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1185 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1190 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1191 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1192 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1193 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1194 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1195 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1196 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1197 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1198 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1199 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1200 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1201 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1202 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1203 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1204 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1205 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1206 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1207 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1208 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1209 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1210 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1211 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1212 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1213 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1214 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1215 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1216 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1217 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1218 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1219 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1220 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1221 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1222 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1223 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1224 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1225 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1226 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1227 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1228 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1229 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1230 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1231 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1232 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1233 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1234 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1235 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1236 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1237 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1238 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1239 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1240 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1241 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1242 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1243 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1244 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1245 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1246 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1247 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1248 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1249 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1250 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1251 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1252 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1253 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1254 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1255 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1256 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1257 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1258 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1259 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1260 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1261 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1262 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1263 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1264 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1265 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1266 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1267 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1268 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1269 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1270 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1271 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1272 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1273 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1274 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1275 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1276 // initialize the samplers to refer to the texture units we use
1277 p->tex_Texture_First = -1;
1278 p->tex_Texture_Second = -1;
1279 p->tex_Texture_GammaRamps = -1;
1280 p->tex_Texture_Normal = -1;
1281 p->tex_Texture_Color = -1;
1282 p->tex_Texture_Gloss = -1;
1283 p->tex_Texture_Glow = -1;
1284 p->tex_Texture_SecondaryNormal = -1;
1285 p->tex_Texture_SecondaryColor = -1;
1286 p->tex_Texture_SecondaryGloss = -1;
1287 p->tex_Texture_SecondaryGlow = -1;
1288 p->tex_Texture_Pants = -1;
1289 p->tex_Texture_Shirt = -1;
1290 p->tex_Texture_FogHeightTexture = -1;
1291 p->tex_Texture_FogMask = -1;
1292 p->tex_Texture_Lightmap = -1;
1293 p->tex_Texture_Deluxemap = -1;
1294 p->tex_Texture_Attenuation = -1;
1295 p->tex_Texture_Cube = -1;
1296 p->tex_Texture_Refraction = -1;
1297 p->tex_Texture_Reflection = -1;
1298 p->tex_Texture_ShadowMap2D = -1;
1299 p->tex_Texture_CubeProjection = -1;
1300 p->tex_Texture_ScreenNormalMap = -1;
1301 p->tex_Texture_ScreenDiffuse = -1;
1302 p->tex_Texture_ScreenSpecular = -1;
1303 p->tex_Texture_ReflectMask = -1;
1304 p->tex_Texture_ReflectCube = -1;
1305 p->tex_Texture_BounceGrid = -1;
1306 // bind the texture samplers in use
1308 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1309 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1310 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1311 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1312 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1313 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1314 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1315 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1316 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1317 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1318 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1319 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1320 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1321 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1322 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1323 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1324 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1325 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1326 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1327 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1328 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1329 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1330 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1331 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1332 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1333 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1334 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1335 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1336 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1337 // get the uniform block indices so we can bind them
1338 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1339 if (vid.support.arb_uniform_buffer_object)
1340 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1343 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1344 // clear the uniform block bindings
1345 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1346 // bind the uniform blocks in use
1348 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1349 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1351 // we're done compiling and setting up the shader, at least until it is used
1353 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1356 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1360 Mem_Free(sourcestring);
1363 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1365 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1366 if (r_glsl_permutation != perm)
1368 r_glsl_permutation = perm;
1369 if (!r_glsl_permutation->program)
1371 if (!r_glsl_permutation->compiled)
1373 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1374 R_GLSL_CompilePermutation(perm, mode, permutation);
1376 if (!r_glsl_permutation->program)
1378 // remove features until we find a valid permutation
1380 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1382 // reduce i more quickly whenever it would not remove any bits
1383 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1384 if (!(permutation & j))
1387 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1388 if (!r_glsl_permutation->compiled)
1389 R_GLSL_CompilePermutation(perm, mode, permutation);
1390 if (r_glsl_permutation->program)
1393 if (i >= SHADERPERMUTATION_COUNT)
1395 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1396 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1397 qglUseProgram(0);CHECKGLERROR
1398 return; // no bit left to clear, entire mode is broken
1403 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1405 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1406 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1407 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1415 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1416 extern D3DCAPS9 vid_d3d9caps;
1419 struct r_hlsl_permutation_s;
1420 typedef struct r_hlsl_permutation_s
1422 /// hash lookup data
1423 struct r_hlsl_permutation_s *hashnext;
1425 unsigned int permutation;
1427 /// indicates if we have tried compiling this permutation already
1429 /// NULL if compilation failed
1430 IDirect3DVertexShader9 *vertexshader;
1431 IDirect3DPixelShader9 *pixelshader;
1433 r_hlsl_permutation_t;
1435 typedef enum D3DVSREGISTER_e
1437 D3DVSREGISTER_TexMatrix = 0, // float4x4
1438 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1439 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1440 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1441 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1442 D3DVSREGISTER_ModelToLight = 20, // float4x4
1443 D3DVSREGISTER_EyePosition = 24,
1444 D3DVSREGISTER_FogPlane = 25,
1445 D3DVSREGISTER_LightDir = 26,
1446 D3DVSREGISTER_LightPosition = 27,
1450 typedef enum D3DPSREGISTER_e
1452 D3DPSREGISTER_Alpha = 0,
1453 D3DPSREGISTER_BloomBlur_Parameters = 1,
1454 D3DPSREGISTER_ClientTime = 2,
1455 D3DPSREGISTER_Color_Ambient = 3,
1456 D3DPSREGISTER_Color_Diffuse = 4,
1457 D3DPSREGISTER_Color_Specular = 5,
1458 D3DPSREGISTER_Color_Glow = 6,
1459 D3DPSREGISTER_Color_Pants = 7,
1460 D3DPSREGISTER_Color_Shirt = 8,
1461 D3DPSREGISTER_DeferredColor_Ambient = 9,
1462 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1463 D3DPSREGISTER_DeferredColor_Specular = 11,
1464 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1465 D3DPSREGISTER_DeferredMod_Specular = 13,
1466 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1467 D3DPSREGISTER_EyePosition = 15, // unused
1468 D3DPSREGISTER_FogColor = 16,
1469 D3DPSREGISTER_FogHeightFade = 17,
1470 D3DPSREGISTER_FogPlane = 18,
1471 D3DPSREGISTER_FogPlaneViewDist = 19,
1472 D3DPSREGISTER_FogRangeRecip = 20,
1473 D3DPSREGISTER_LightColor = 21,
1474 D3DPSREGISTER_LightDir = 22, // unused
1475 D3DPSREGISTER_LightPosition = 23,
1476 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1477 D3DPSREGISTER_PixelSize = 25,
1478 D3DPSREGISTER_ReflectColor = 26,
1479 D3DPSREGISTER_ReflectFactor = 27,
1480 D3DPSREGISTER_ReflectOffset = 28,
1481 D3DPSREGISTER_RefractColor = 29,
1482 D3DPSREGISTER_Saturation = 30,
1483 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1484 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1485 D3DPSREGISTER_ScreenToDepth = 33,
1486 D3DPSREGISTER_ShadowMap_Parameters = 34,
1487 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1488 D3DPSREGISTER_SpecularPower = 36,
1489 D3DPSREGISTER_UserVec1 = 37,
1490 D3DPSREGISTER_UserVec2 = 38,
1491 D3DPSREGISTER_UserVec3 = 39,
1492 D3DPSREGISTER_UserVec4 = 40,
1493 D3DPSREGISTER_ViewTintColor = 41,
1494 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1495 D3DPSREGISTER_BloomColorSubtract = 43,
1496 D3DPSREGISTER_ViewToLight = 44, // float4x4
1497 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1498 D3DPSREGISTER_NormalmapScrollBlend = 52,
1499 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1500 D3DPSREGISTER_OffsetMapping_Bias = 54,
1505 /// information about each possible shader permutation
1506 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1507 /// currently selected permutation
1508 r_hlsl_permutation_t *r_hlsl_permutation;
1509 /// storage for permutations linked in the hash table
1510 memexpandablearray_t r_hlsl_permutationarray;
1512 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1514 //unsigned int hashdepth = 0;
1515 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1516 r_hlsl_permutation_t *p;
1517 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1519 if (p->mode == mode && p->permutation == permutation)
1521 //if (hashdepth > 10)
1522 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1527 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1529 p->permutation = permutation;
1530 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1531 r_hlsl_permutationhash[mode][hashindex] = p;
1532 //if (hashdepth > 10)
1533 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1538 //#include <d3dx9shader.h>
1539 //#include <d3dx9mesh.h>
1541 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1543 DWORD *vsbin = NULL;
1544 DWORD *psbin = NULL;
1545 fs_offset_t vsbinsize;
1546 fs_offset_t psbinsize;
1547 // IDirect3DVertexShader9 *vs = NULL;
1548 // IDirect3DPixelShader9 *ps = NULL;
1549 ID3DXBuffer *vslog = NULL;
1550 ID3DXBuffer *vsbuffer = NULL;
1551 ID3DXConstantTable *vsconstanttable = NULL;
1552 ID3DXBuffer *pslog = NULL;
1553 ID3DXBuffer *psbuffer = NULL;
1554 ID3DXConstantTable *psconstanttable = NULL;
1557 char temp[MAX_INPUTLINE];
1558 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1560 qboolean debugshader = gl_paranoid.integer != 0;
1561 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1562 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1565 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1566 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1568 if ((!vsbin && vertstring) || (!psbin && fragstring))
1570 const char* dllnames_d3dx9 [] =
1594 dllhandle_t d3dx9_dll = NULL;
1595 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1596 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1597 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1598 dllfunction_t d3dx9_dllfuncs[] =
1600 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1601 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1602 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1605 // 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...
1606 #ifndef ID3DXBuffer_GetBufferPointer
1607 #if !defined(__cplusplus) || defined(CINTERFACE)
1608 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1609 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1610 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1612 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1613 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1614 #define ID3DXBuffer_Release(p) (p)->Release()
1617 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1619 DWORD shaderflags = 0;
1621 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1622 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1623 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1624 if (vertstring && vertstring[0])
1628 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1629 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1632 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1635 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1636 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1637 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1638 ID3DXBuffer_Release(vsbuffer);
1642 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1643 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1644 ID3DXBuffer_Release(vslog);
1647 if (fragstring && fragstring[0])
1651 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1652 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1655 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1658 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1659 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1660 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1661 ID3DXBuffer_Release(psbuffer);
1665 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1666 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1667 ID3DXBuffer_Release(pslog);
1670 Sys_UnloadLibrary(&d3dx9_dll);
1673 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1677 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1678 if (FAILED(vsresult))
1679 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1680 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1681 if (FAILED(psresult))
1682 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1684 // free the shader data
1685 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1686 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1689 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1692 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1693 int vertstring_length = 0;
1694 int geomstring_length = 0;
1695 int fragstring_length = 0;
1698 char *vertstring, *geomstring, *fragstring;
1699 char permutationname[256];
1700 char cachename[256];
1701 int vertstrings_count = 0;
1702 int geomstrings_count = 0;
1703 int fragstrings_count = 0;
1704 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1705 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1706 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1711 p->vertexshader = NULL;
1712 p->pixelshader = NULL;
1714 permutationname[0] = 0;
1716 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1718 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1719 strlcat(cachename, "hlsl/", sizeof(cachename));
1721 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1722 vertstrings_count = 0;
1723 geomstrings_count = 0;
1724 fragstrings_count = 0;
1725 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1726 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1727 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1729 // the first pretext is which type of shader to compile as
1730 // (later these will all be bound together as a program object)
1731 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1732 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1733 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1735 // the second pretext is the mode (for example a light source)
1736 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1737 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1738 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1739 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1740 strlcat(cachename, modeinfo->name, sizeof(cachename));
1742 // now add all the permutation pretexts
1743 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1745 if (permutation & (1<<i))
1747 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1748 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1749 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1750 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1751 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1755 // keep line numbers correct
1756 vertstrings_list[vertstrings_count++] = "\n";
1757 geomstrings_list[geomstrings_count++] = "\n";
1758 fragstrings_list[fragstrings_count++] = "\n";
1763 R_CompileShader_AddStaticParms(mode, permutation);
1764 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1765 vertstrings_count += shaderstaticparms_count;
1766 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1767 geomstrings_count += shaderstaticparms_count;
1768 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1769 fragstrings_count += shaderstaticparms_count;
1771 // replace spaces in the cachename with _ characters
1772 for (i = 0;cachename[i];i++)
1773 if (cachename[i] == ' ')
1776 // now append the shader text itself
1777 vertstrings_list[vertstrings_count++] = sourcestring;
1778 geomstrings_list[geomstrings_count++] = sourcestring;
1779 fragstrings_list[fragstrings_count++] = sourcestring;
1781 vertstring_length = 0;
1782 for (i = 0;i < vertstrings_count;i++)
1783 vertstring_length += strlen(vertstrings_list[i]);
1784 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1785 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1786 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1788 geomstring_length = 0;
1789 for (i = 0;i < geomstrings_count;i++)
1790 geomstring_length += strlen(geomstrings_list[i]);
1791 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1792 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1793 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1795 fragstring_length = 0;
1796 for (i = 0;i < fragstrings_count;i++)
1797 fragstring_length += strlen(fragstrings_list[i]);
1798 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1799 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1800 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1802 // try to load the cached shader, or generate one
1803 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1805 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1806 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1808 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1812 Mem_Free(vertstring);
1814 Mem_Free(geomstring);
1816 Mem_Free(fragstring);
1818 Mem_Free(sourcestring);
1821 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1822 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1823 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);}
1824 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);}
1825 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);}
1826 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);}
1828 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1829 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1830 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);}
1831 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);}
1832 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);}
1833 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);}
1835 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1837 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1838 if (r_hlsl_permutation != perm)
1840 r_hlsl_permutation = perm;
1841 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1843 if (!r_hlsl_permutation->compiled)
1844 R_HLSL_CompilePermutation(perm, mode, permutation);
1845 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1847 // remove features until we find a valid permutation
1849 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1851 // reduce i more quickly whenever it would not remove any bits
1852 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1853 if (!(permutation & j))
1856 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1857 if (!r_hlsl_permutation->compiled)
1858 R_HLSL_CompilePermutation(perm, mode, permutation);
1859 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1862 if (i >= SHADERPERMUTATION_COUNT)
1864 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1865 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1866 return; // no bit left to clear, entire mode is broken
1870 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1871 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1873 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1874 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1875 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1879 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1881 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1882 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1883 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1884 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1887 void R_GLSL_Restart_f(void)
1889 unsigned int i, limit;
1890 if (glslshaderstring)
1891 Mem_Free(glslshaderstring);
1892 glslshaderstring = NULL;
1893 if (hlslshaderstring)
1894 Mem_Free(hlslshaderstring);
1895 hlslshaderstring = NULL;
1896 switch(vid.renderpath)
1898 case RENDERPATH_D3D9:
1901 r_hlsl_permutation_t *p;
1902 r_hlsl_permutation = NULL;
1903 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1904 for (i = 0;i < limit;i++)
1906 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1908 if (p->vertexshader)
1909 IDirect3DVertexShader9_Release(p->vertexshader);
1911 IDirect3DPixelShader9_Release(p->pixelshader);
1912 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1915 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1919 case RENDERPATH_D3D10:
1920 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1922 case RENDERPATH_D3D11:
1923 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1925 case RENDERPATH_GL20:
1926 case RENDERPATH_GLES2:
1928 r_glsl_permutation_t *p;
1929 r_glsl_permutation = NULL;
1930 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1931 for (i = 0;i < limit;i++)
1933 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1935 GL_Backend_FreeProgram(p->program);
1936 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1939 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1942 case RENDERPATH_GL11:
1943 case RENDERPATH_GL13:
1944 case RENDERPATH_GLES1:
1946 case RENDERPATH_SOFT:
1951 static void R_GLSL_DumpShader_f(void)
1953 int i, language, mode, dupe;
1955 shadermodeinfo_t *modeinfo;
1958 for (language = 0;language < 2;language++)
1960 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1961 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1963 // don't dump the same file multiple times (most or all shaders come from the same file)
1964 for (dupe = mode - 1;dupe >= 0;dupe--)
1965 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1969 text = R_GetShaderText(modeinfo[mode].filename, false, true);
1972 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1975 FS_Print(file, "/* The engine may define the following macros:\n");
1976 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1977 for (i = 0;i < SHADERMODE_COUNT;i++)
1978 FS_Print(file, modeinfo[i].pretext);
1979 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1980 FS_Print(file, shaderpermutationinfo[i].pretext);
1981 FS_Print(file, "*/\n");
1982 FS_Print(file, text);
1984 Con_Printf("%s written\n", modeinfo[mode].filename);
1987 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1993 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1995 unsigned int permutation = 0;
1996 if (r_trippy.integer && !notrippy)
1997 permutation |= SHADERPERMUTATION_TRIPPY;
1998 permutation |= SHADERPERMUTATION_VIEWTINT;
2000 permutation |= SHADERPERMUTATION_DIFFUSE;
2002 permutation |= SHADERPERMUTATION_SPECULAR;
2003 if (texturemode == GL_MODULATE)
2004 permutation |= SHADERPERMUTATION_COLORMAPPING;
2005 else if (texturemode == GL_ADD)
2006 permutation |= SHADERPERMUTATION_GLOW;
2007 else if (texturemode == GL_DECAL)
2008 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2009 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2010 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2011 if (suppresstexalpha)
2012 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2014 texturemode = GL_MODULATE;
2015 if (vid.allowalphatocoverage)
2016 GL_AlphaToCoverage(false);
2017 switch (vid.renderpath)
2019 case RENDERPATH_D3D9:
2021 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2022 R_Mesh_TexBind(GL20TU_FIRST , first );
2023 R_Mesh_TexBind(GL20TU_SECOND, second);
2024 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2025 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2028 case RENDERPATH_D3D10:
2029 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2031 case RENDERPATH_D3D11:
2032 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2034 case RENDERPATH_GL20:
2035 case RENDERPATH_GLES2:
2036 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2037 if (r_glsl_permutation->tex_Texture_First >= 0)
2038 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2039 if (r_glsl_permutation->tex_Texture_Second >= 0)
2040 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2041 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2042 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2044 case RENDERPATH_GL13:
2045 case RENDERPATH_GLES1:
2046 R_Mesh_TexBind(0, first );
2047 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2048 R_Mesh_TexMatrix(0, NULL);
2049 R_Mesh_TexBind(1, second);
2052 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2053 R_Mesh_TexMatrix(1, NULL);
2056 case RENDERPATH_GL11:
2057 R_Mesh_TexBind(0, first );
2058 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2059 R_Mesh_TexMatrix(0, NULL);
2061 case RENDERPATH_SOFT:
2062 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2063 R_Mesh_TexBind(GL20TU_FIRST , first );
2064 R_Mesh_TexBind(GL20TU_SECOND, second);
2069 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2071 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2074 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2076 unsigned int permutation = 0;
2077 if (r_trippy.integer && !notrippy)
2078 permutation |= SHADERPERMUTATION_TRIPPY;
2080 permutation |= SHADERPERMUTATION_DEPTHRGB;
2082 permutation |= SHADERPERMUTATION_SKELETAL;
2084 if (vid.allowalphatocoverage)
2085 GL_AlphaToCoverage(false);
2086 switch (vid.renderpath)
2088 case RENDERPATH_D3D9:
2090 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2093 case RENDERPATH_D3D10:
2094 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2096 case RENDERPATH_D3D11:
2097 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2099 case RENDERPATH_GL20:
2100 case RENDERPATH_GLES2:
2101 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2102 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2103 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);
2106 case RENDERPATH_GL13:
2107 case RENDERPATH_GLES1:
2108 R_Mesh_TexBind(0, 0);
2109 R_Mesh_TexBind(1, 0);
2111 case RENDERPATH_GL11:
2112 R_Mesh_TexBind(0, 0);
2114 case RENDERPATH_SOFT:
2115 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2120 extern qboolean r_shadow_usingdeferredprepass;
2121 extern rtexture_t *r_shadow_attenuationgradienttexture;
2122 extern rtexture_t *r_shadow_attenuation2dtexture;
2123 extern rtexture_t *r_shadow_attenuation3dtexture;
2124 extern qboolean r_shadow_usingshadowmap2d;
2125 extern qboolean r_shadow_usingshadowmaportho;
2126 extern float r_shadow_shadowmap_texturescale[2];
2127 extern float r_shadow_shadowmap_parameters[4];
2128 extern qboolean r_shadow_shadowmapvsdct;
2129 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2130 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2131 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2132 extern matrix4x4_t r_shadow_shadowmapmatrix;
2133 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2134 extern int r_shadow_prepass_width;
2135 extern int r_shadow_prepass_height;
2136 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2137 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2138 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2139 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2141 #define BLENDFUNC_ALLOWS_COLORMOD 1
2142 #define BLENDFUNC_ALLOWS_FOG 2
2143 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2144 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2145 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2146 static int R_BlendFuncFlags(int src, int dst)
2150 // a blendfunc allows colormod if:
2151 // a) it can never keep the destination pixel invariant, or
2152 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2153 // this is to prevent unintended side effects from colormod
2155 // a blendfunc allows fog if:
2156 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2157 // this is to prevent unintended side effects from fog
2159 // these checks are the output of fogeval.pl
2161 r |= BLENDFUNC_ALLOWS_COLORMOD;
2162 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2163 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2164 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2165 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2166 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2167 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2168 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2169 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2170 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2171 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2172 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2173 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2174 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2175 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2177 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2178 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2180 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2181 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2182 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2187 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)
2189 // select a permutation of the lighting shader appropriate to this
2190 // combination of texture, entity, light source, and fogging, only use the
2191 // minimum features necessary to avoid wasting rendering time in the
2192 // fragment shader on features that are not being used
2193 unsigned int permutation = 0;
2194 unsigned int mode = 0;
2196 static float dummy_colormod[3] = {1, 1, 1};
2197 float *colormod = rsurface.colormod;
2199 matrix4x4_t tempmatrix;
2200 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2201 if (r_trippy.integer && !notrippy)
2202 permutation |= SHADERPERMUTATION_TRIPPY;
2203 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2204 permutation |= SHADERPERMUTATION_ALPHAKILL;
2205 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2206 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2207 if (rsurfacepass == RSURFPASS_BACKGROUND)
2209 // distorted background
2210 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2212 mode = SHADERMODE_WATER;
2213 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2214 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2215 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2217 // this is the right thing to do for wateralpha
2218 GL_BlendFunc(GL_ONE, GL_ZERO);
2219 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2223 // this is the right thing to do for entity alpha
2224 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2225 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2228 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2230 mode = SHADERMODE_REFRACTION;
2231 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2232 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2233 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2234 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2238 mode = SHADERMODE_GENERIC;
2239 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2240 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2243 if (vid.allowalphatocoverage)
2244 GL_AlphaToCoverage(false);
2246 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2248 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2250 switch(rsurface.texture->offsetmapping)
2252 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2253 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2254 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2255 case OFFSETMAPPING_OFF: break;
2258 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2259 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2260 // normalmap (deferred prepass), may use alpha test on diffuse
2261 mode = SHADERMODE_DEFERREDGEOMETRY;
2262 GL_BlendFunc(GL_ONE, GL_ZERO);
2263 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2264 if (vid.allowalphatocoverage)
2265 GL_AlphaToCoverage(false);
2267 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2269 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2271 switch(rsurface.texture->offsetmapping)
2273 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2274 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2275 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2276 case OFFSETMAPPING_OFF: break;
2279 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2280 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2281 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2282 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2284 mode = SHADERMODE_LIGHTSOURCE;
2285 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2286 permutation |= SHADERPERMUTATION_CUBEFILTER;
2287 if (diffusescale > 0)
2288 permutation |= SHADERPERMUTATION_DIFFUSE;
2289 if (specularscale > 0)
2290 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2291 if (r_refdef.fogenabled)
2292 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2293 if (rsurface.texture->colormapping)
2294 permutation |= SHADERPERMUTATION_COLORMAPPING;
2295 if (r_shadow_usingshadowmap2d)
2297 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2298 if(r_shadow_shadowmapvsdct)
2299 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2301 if (r_shadow_shadowmap2ddepthbuffer)
2302 permutation |= SHADERPERMUTATION_DEPTHRGB;
2304 if (rsurface.texture->reflectmasktexture)
2305 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2306 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2307 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2308 if (vid.allowalphatocoverage)
2309 GL_AlphaToCoverage(false);
2311 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2313 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2315 switch(rsurface.texture->offsetmapping)
2317 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2318 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2319 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2320 case OFFSETMAPPING_OFF: break;
2323 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2324 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2325 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2326 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2327 // unshaded geometry (fullbright or ambient model lighting)
2328 mode = SHADERMODE_FLATCOLOR;
2329 ambientscale = diffusescale = specularscale = 0;
2330 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2331 permutation |= SHADERPERMUTATION_GLOW;
2332 if (r_refdef.fogenabled)
2333 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2334 if (rsurface.texture->colormapping)
2335 permutation |= SHADERPERMUTATION_COLORMAPPING;
2336 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2338 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2339 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2341 if (r_shadow_shadowmap2ddepthbuffer)
2342 permutation |= SHADERPERMUTATION_DEPTHRGB;
2344 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2345 permutation |= SHADERPERMUTATION_REFLECTION;
2346 if (rsurface.texture->reflectmasktexture)
2347 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2348 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2349 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2350 // when using alphatocoverage, we don't need alphakill
2351 if (vid.allowalphatocoverage)
2353 if (r_transparent_alphatocoverage.integer)
2355 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2356 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2359 GL_AlphaToCoverage(false);
2362 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2364 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2366 switch(rsurface.texture->offsetmapping)
2368 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2369 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2370 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2371 case OFFSETMAPPING_OFF: break;
2374 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2375 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2376 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2377 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2378 // directional model lighting
2379 mode = SHADERMODE_LIGHTDIRECTION;
2380 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2381 permutation |= SHADERPERMUTATION_GLOW;
2382 permutation |= SHADERPERMUTATION_DIFFUSE;
2383 if (specularscale > 0)
2384 permutation |= SHADERPERMUTATION_SPECULAR;
2385 if (r_refdef.fogenabled)
2386 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2387 if (rsurface.texture->colormapping)
2388 permutation |= SHADERPERMUTATION_COLORMAPPING;
2389 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2391 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2392 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2394 if (r_shadow_shadowmap2ddepthbuffer)
2395 permutation |= SHADERPERMUTATION_DEPTHRGB;
2397 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2398 permutation |= SHADERPERMUTATION_REFLECTION;
2399 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2400 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2401 if (rsurface.texture->reflectmasktexture)
2402 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2403 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2405 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2406 if (r_shadow_bouncegriddirectional)
2407 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2409 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2410 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2411 // when using alphatocoverage, we don't need alphakill
2412 if (vid.allowalphatocoverage)
2414 if (r_transparent_alphatocoverage.integer)
2416 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2417 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2420 GL_AlphaToCoverage(false);
2423 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2425 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2427 switch(rsurface.texture->offsetmapping)
2429 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2430 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2431 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2432 case OFFSETMAPPING_OFF: break;
2435 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2436 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2437 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2438 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2439 // ambient model lighting
2440 mode = SHADERMODE_LIGHTDIRECTION;
2441 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2442 permutation |= SHADERPERMUTATION_GLOW;
2443 if (r_refdef.fogenabled)
2444 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2445 if (rsurface.texture->colormapping)
2446 permutation |= SHADERPERMUTATION_COLORMAPPING;
2447 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2449 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2450 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2452 if (r_shadow_shadowmap2ddepthbuffer)
2453 permutation |= SHADERPERMUTATION_DEPTHRGB;
2455 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2456 permutation |= SHADERPERMUTATION_REFLECTION;
2457 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2458 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2459 if (rsurface.texture->reflectmasktexture)
2460 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2461 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2463 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2464 if (r_shadow_bouncegriddirectional)
2465 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2467 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2468 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2469 // when using alphatocoverage, we don't need alphakill
2470 if (vid.allowalphatocoverage)
2472 if (r_transparent_alphatocoverage.integer)
2474 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2475 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2478 GL_AlphaToCoverage(false);
2483 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2485 switch(rsurface.texture->offsetmapping)
2487 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2488 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2489 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2490 case OFFSETMAPPING_OFF: break;
2493 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2494 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2495 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2496 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2498 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2499 permutation |= SHADERPERMUTATION_GLOW;
2500 if (r_refdef.fogenabled)
2501 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2502 if (rsurface.texture->colormapping)
2503 permutation |= SHADERPERMUTATION_COLORMAPPING;
2504 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2506 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2507 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2509 if (r_shadow_shadowmap2ddepthbuffer)
2510 permutation |= SHADERPERMUTATION_DEPTHRGB;
2512 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2513 permutation |= SHADERPERMUTATION_REFLECTION;
2514 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2515 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2516 if (rsurface.texture->reflectmasktexture)
2517 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2518 if (FAKELIGHT_ENABLED)
2520 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2521 mode = SHADERMODE_FAKELIGHT;
2522 permutation |= SHADERPERMUTATION_DIFFUSE;
2523 if (specularscale > 0)
2524 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2526 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2528 // deluxemapping (light direction texture)
2529 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2530 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2532 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2533 permutation |= SHADERPERMUTATION_DIFFUSE;
2534 if (specularscale > 0)
2535 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2537 else if (r_glsl_deluxemapping.integer >= 2)
2539 // fake deluxemapping (uniform light direction in tangentspace)
2540 if (rsurface.uselightmaptexture)
2541 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2543 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2544 permutation |= SHADERPERMUTATION_DIFFUSE;
2545 if (specularscale > 0)
2546 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2548 else if (rsurface.uselightmaptexture)
2550 // ordinary lightmapping (q1bsp, q3bsp)
2551 mode = SHADERMODE_LIGHTMAP;
2555 // ordinary vertex coloring (q3bsp)
2556 mode = SHADERMODE_VERTEXCOLOR;
2558 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2560 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2561 if (r_shadow_bouncegriddirectional)
2562 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2564 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2565 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2566 // when using alphatocoverage, we don't need alphakill
2567 if (vid.allowalphatocoverage)
2569 if (r_transparent_alphatocoverage.integer)
2571 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2572 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2575 GL_AlphaToCoverage(false);
2578 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2579 colormod = dummy_colormod;
2580 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2581 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2582 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2583 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2584 switch(vid.renderpath)
2586 case RENDERPATH_D3D9:
2588 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);
2589 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2590 R_SetupShader_SetPermutationHLSL(mode, permutation);
2591 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2592 if (mode == SHADERMODE_LIGHTSOURCE)
2594 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2595 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2599 if (mode == SHADERMODE_LIGHTDIRECTION)
2601 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2604 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2605 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2606 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2607 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2608 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2610 if (mode == SHADERMODE_LIGHTSOURCE)
2612 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2613 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2614 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2615 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2616 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2618 // additive passes are only darkened by fog, not tinted
2619 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2620 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2624 if (mode == SHADERMODE_FLATCOLOR)
2626 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2628 else if (mode == SHADERMODE_LIGHTDIRECTION)
2630 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]);
2631 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2632 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);
2633 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2634 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2635 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2636 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2640 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2641 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2642 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);
2643 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2644 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2646 // additive passes are only darkened by fog, not tinted
2647 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2648 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2650 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2651 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);
2652 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2653 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2654 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2655 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2656 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2657 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2658 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2659 if (mode == SHADERMODE_WATER)
2660 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2662 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2663 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2664 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2665 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));
2666 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2667 if (rsurface.texture->pantstexture)
2668 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2670 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2671 if (rsurface.texture->shirttexture)
2672 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2674 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2675 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2676 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2677 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2678 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2679 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2680 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2681 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2682 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2683 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2685 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2686 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2687 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2688 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2690 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2691 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2692 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2693 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2694 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2695 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2696 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2697 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2698 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2699 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2700 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2701 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2702 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2703 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2704 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2705 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2706 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2707 if (rsurfacepass == RSURFPASS_BACKGROUND)
2709 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2710 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2711 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2715 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2717 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2718 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2719 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2720 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2722 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2723 if (rsurface.rtlight)
2725 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2726 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2731 case RENDERPATH_D3D10:
2732 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2734 case RENDERPATH_D3D11:
2735 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2737 case RENDERPATH_GL20:
2738 case RENDERPATH_GLES2:
2739 if (!vid.useinterleavedarrays)
2741 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);
2742 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2743 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2744 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2745 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2746 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2747 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2748 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2749 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2750 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2751 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2755 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);
2756 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2758 // this has to be after RSurf_PrepareVerticesForBatch
2759 if (rsurface.batchskeletaltransform3x4buffer)
2760 permutation |= SHADERPERMUTATION_SKELETAL;
2761 R_SetupShader_SetPermutationGLSL(mode, permutation);
2762 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2763 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);
2765 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2766 if (mode == SHADERMODE_LIGHTSOURCE)
2768 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2769 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2770 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2771 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2772 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2773 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);
2775 // additive passes are only darkened by fog, not tinted
2776 if (r_glsl_permutation->loc_FogColor >= 0)
2777 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2778 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);
2782 if (mode == SHADERMODE_FLATCOLOR)
2784 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2786 else if (mode == SHADERMODE_LIGHTDIRECTION)
2788 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]);
2789 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]);
2790 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);
2791 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2792 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2793 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]);
2794 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]);
2798 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]);
2799 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]);
2800 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);
2801 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2802 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2804 // additive passes are only darkened by fog, not tinted
2805 if (r_glsl_permutation->loc_FogColor >= 0)
2807 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2808 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2810 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2812 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);
2813 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]);
2814 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]);
2815 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]);
2816 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]);
2817 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2818 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2819 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);
2820 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]);
2822 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2823 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2824 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2825 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]);
2826 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]);
2828 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2829 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));
2830 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2831 if (r_glsl_permutation->loc_Color_Pants >= 0)
2833 if (rsurface.texture->pantstexture)
2834 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2836 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2838 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2840 if (rsurface.texture->shirttexture)
2841 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2843 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2845 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]);
2846 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2847 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2848 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2849 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2850 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2851 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2852 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2853 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2855 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);
2856 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2857 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]);
2858 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2859 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);}
2860 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2862 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2863 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2864 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2865 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2866 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2867 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2868 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2869 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2870 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2871 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2872 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2873 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2874 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2875 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2876 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);
2877 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2878 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2879 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2880 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2881 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2882 if (rsurfacepass == RSURFPASS_BACKGROUND)
2884 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);
2885 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);
2886 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);
2890 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);
2892 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2893 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2894 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2895 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2897 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2898 if (rsurface.rtlight)
2900 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2901 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2904 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2907 case RENDERPATH_GL11:
2908 case RENDERPATH_GL13:
2909 case RENDERPATH_GLES1:
2911 case RENDERPATH_SOFT:
2912 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);
2913 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2914 R_SetupShader_SetPermutationSoft(mode, permutation);
2915 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2916 if (mode == SHADERMODE_LIGHTSOURCE)
2918 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2919 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2920 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2921 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2922 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2923 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2925 // additive passes are only darkened by fog, not tinted
2926 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2927 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2931 if (mode == SHADERMODE_FLATCOLOR)
2933 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2935 else if (mode == SHADERMODE_LIGHTDIRECTION)
2937 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]);
2938 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2939 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);
2940 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2941 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2942 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]);
2943 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2947 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2948 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2949 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);
2950 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2951 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2953 // additive passes are only darkened by fog, not tinted
2954 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2955 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2957 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2958 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);
2959 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]);
2960 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]);
2961 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]);
2962 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]);
2963 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2964 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2965 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2966 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2968 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2969 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2970 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2971 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2972 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]);
2974 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2975 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));
2976 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2977 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2979 if (rsurface.texture->pantstexture)
2980 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2982 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2984 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2986 if (rsurface.texture->shirttexture)
2987 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2989 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2991 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2992 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2993 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2994 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2995 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2996 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2997 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2998 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2999 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3001 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3002 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3003 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3004 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3006 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3007 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3008 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3009 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3010 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3011 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3012 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3013 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3014 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3015 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3016 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3017 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3018 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3019 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3020 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3021 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3022 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3023 if (rsurfacepass == RSURFPASS_BACKGROUND)
3025 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3026 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3027 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3031 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3033 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3034 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3035 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3036 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3038 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3039 if (rsurface.rtlight)
3041 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3042 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3049 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3051 // select a permutation of the lighting shader appropriate to this
3052 // combination of texture, entity, light source, and fogging, only use the
3053 // minimum features necessary to avoid wasting rendering time in the
3054 // fragment shader on features that are not being used
3055 unsigned int permutation = 0;
3056 unsigned int mode = 0;
3057 const float *lightcolorbase = rtlight->currentcolor;
3058 float ambientscale = rtlight->ambientscale;
3059 float diffusescale = rtlight->diffusescale;
3060 float specularscale = rtlight->specularscale;
3061 // this is the location of the light in view space
3062 vec3_t viewlightorigin;
3063 // this transforms from view space (camera) to light space (cubemap)
3064 matrix4x4_t viewtolight;
3065 matrix4x4_t lighttoview;
3066 float viewtolight16f[16];
3068 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3069 if (rtlight->currentcubemap != r_texture_whitecube)
3070 permutation |= SHADERPERMUTATION_CUBEFILTER;
3071 if (diffusescale > 0)
3072 permutation |= SHADERPERMUTATION_DIFFUSE;
3073 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3074 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3075 if (r_shadow_usingshadowmap2d)
3077 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3078 if (r_shadow_shadowmapvsdct)
3079 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3081 if (r_shadow_shadowmap2ddepthbuffer)
3082 permutation |= SHADERPERMUTATION_DEPTHRGB;
3084 if (vid.allowalphatocoverage)
3085 GL_AlphaToCoverage(false);
3086 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3087 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3088 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3089 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3090 switch(vid.renderpath)
3092 case RENDERPATH_D3D9:
3094 R_SetupShader_SetPermutationHLSL(mode, permutation);
3095 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3096 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3097 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3098 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3099 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3100 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3101 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3102 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);
3103 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3104 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3106 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3107 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3108 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3109 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3110 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3113 case RENDERPATH_D3D10:
3114 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3116 case RENDERPATH_D3D11:
3117 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3119 case RENDERPATH_GL20:
3120 case RENDERPATH_GLES2:
3121 R_SetupShader_SetPermutationGLSL(mode, permutation);
3122 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3123 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3124 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3125 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3126 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3127 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]);
3128 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]);
3129 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);
3130 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]);
3131 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3133 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3134 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3135 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3136 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3137 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3139 case RENDERPATH_GL11:
3140 case RENDERPATH_GL13:
3141 case RENDERPATH_GLES1:
3143 case RENDERPATH_SOFT:
3144 R_SetupShader_SetPermutationGLSL(mode, permutation);
3145 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3146 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3147 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3148 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3149 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3150 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3151 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]);
3152 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);
3153 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3154 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3156 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3157 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3158 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3159 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3160 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3165 #define SKINFRAME_HASH 1024
3169 int loadsequence; // incremented each level change
3170 memexpandablearray_t array;
3171 skinframe_t *hash[SKINFRAME_HASH];
3174 r_skinframe_t r_skinframe;
3176 void R_SkinFrame_PrepareForPurge(void)
3178 r_skinframe.loadsequence++;
3179 // wrap it without hitting zero
3180 if (r_skinframe.loadsequence >= 200)
3181 r_skinframe.loadsequence = 1;
3184 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3188 // mark the skinframe as used for the purging code
3189 skinframe->loadsequence = r_skinframe.loadsequence;
3192 void R_SkinFrame_Purge(void)
3196 for (i = 0;i < SKINFRAME_HASH;i++)
3198 for (s = r_skinframe.hash[i];s;s = s->next)
3200 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3202 if (s->merged == s->base)
3204 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3205 R_PurgeTexture(s->stain );s->stain = NULL;
3206 R_PurgeTexture(s->merged);s->merged = NULL;
3207 R_PurgeTexture(s->base );s->base = NULL;
3208 R_PurgeTexture(s->pants );s->pants = NULL;
3209 R_PurgeTexture(s->shirt );s->shirt = NULL;
3210 R_PurgeTexture(s->nmap );s->nmap = NULL;
3211 R_PurgeTexture(s->gloss );s->gloss = NULL;
3212 R_PurgeTexture(s->glow );s->glow = NULL;
3213 R_PurgeTexture(s->fog );s->fog = NULL;
3214 R_PurgeTexture(s->reflect);s->reflect = NULL;
3215 s->loadsequence = 0;
3221 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3223 char basename[MAX_QPATH];
3225 Image_StripImageExtension(name, basename, sizeof(basename));
3227 if( last == NULL ) {
3229 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3230 item = r_skinframe.hash[hashindex];
3235 // linearly search through the hash bucket
3236 for( ; item ; item = item->next ) {
3237 if( !strcmp( item->basename, basename ) ) {
3244 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3248 char basename[MAX_QPATH];
3250 Image_StripImageExtension(name, basename, sizeof(basename));
3252 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3253 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3254 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3258 rtexture_t *dyntexture;
3259 // check whether its a dynamic texture
3260 dyntexture = CL_GetDynTexture( basename );
3261 if (!add && !dyntexture)
3263 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3264 memset(item, 0, sizeof(*item));
3265 strlcpy(item->basename, basename, sizeof(item->basename));
3266 item->base = dyntexture; // either NULL or dyntexture handle
3267 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3268 item->comparewidth = comparewidth;
3269 item->compareheight = compareheight;
3270 item->comparecrc = comparecrc;
3271 item->next = r_skinframe.hash[hashindex];
3272 r_skinframe.hash[hashindex] = item;
3274 else if (textureflags & TEXF_FORCE_RELOAD)
3276 rtexture_t *dyntexture;
3277 // check whether its a dynamic texture
3278 dyntexture = CL_GetDynTexture( basename );
3279 if (!add && !dyntexture)
3281 if (item->merged == item->base)
3282 item->merged = NULL;
3283 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3284 R_PurgeTexture(item->stain );item->stain = NULL;
3285 R_PurgeTexture(item->merged);item->merged = NULL;
3286 R_PurgeTexture(item->base );item->base = NULL;
3287 R_PurgeTexture(item->pants );item->pants = NULL;
3288 R_PurgeTexture(item->shirt );item->shirt = NULL;
3289 R_PurgeTexture(item->nmap );item->nmap = NULL;
3290 R_PurgeTexture(item->gloss );item->gloss = NULL;
3291 R_PurgeTexture(item->glow );item->glow = NULL;
3292 R_PurgeTexture(item->fog );item->fog = NULL;
3293 R_PurgeTexture(item->reflect);item->reflect = NULL;
3294 item->loadsequence = 0;
3296 else if( item->base == NULL )
3298 rtexture_t *dyntexture;
3299 // check whether its a dynamic texture
3300 // 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]
3301 dyntexture = CL_GetDynTexture( basename );
3302 item->base = dyntexture; // either NULL or dyntexture handle
3305 R_SkinFrame_MarkUsed(item);
3309 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3311 unsigned long long avgcolor[5], wsum; \
3319 for(pix = 0; pix < cnt; ++pix) \
3322 for(comp = 0; comp < 3; ++comp) \
3324 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3327 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3329 for(comp = 0; comp < 3; ++comp) \
3330 avgcolor[comp] += getpixel * w; \
3333 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3334 avgcolor[4] += getpixel; \
3336 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3338 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3339 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3340 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3341 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3344 extern cvar_t gl_picmip;
3345 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3348 unsigned char *pixels;
3349 unsigned char *bumppixels;
3350 unsigned char *basepixels = NULL;
3351 int basepixels_width = 0;
3352 int basepixels_height = 0;
3353 skinframe_t *skinframe;
3354 rtexture_t *ddsbase = NULL;
3355 qboolean ddshasalpha = false;
3356 float ddsavgcolor[4];
3357 char basename[MAX_QPATH];
3358 int miplevel = R_PicmipForFlags(textureflags);
3359 int savemiplevel = miplevel;
3363 if (cls.state == ca_dedicated)
3366 // return an existing skinframe if already loaded
3367 // if loading of the first image fails, don't make a new skinframe as it
3368 // would cause all future lookups of this to be missing
3369 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3370 if (skinframe && skinframe->base)
3373 Image_StripImageExtension(name, basename, sizeof(basename));
3375 // check for DDS texture file first
3376 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3378 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3379 if (basepixels == NULL)
3383 // FIXME handle miplevel
3385 if (developer_loading.integer)
3386 Con_Printf("loading skin \"%s\"\n", name);
3388 // we've got some pixels to store, so really allocate this new texture now
3390 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3391 textureflags &= ~TEXF_FORCE_RELOAD;
3392 skinframe->stain = NULL;
3393 skinframe->merged = NULL;
3394 skinframe->base = NULL;
3395 skinframe->pants = NULL;
3396 skinframe->shirt = NULL;
3397 skinframe->nmap = NULL;
3398 skinframe->gloss = NULL;
3399 skinframe->glow = NULL;
3400 skinframe->fog = NULL;
3401 skinframe->reflect = NULL;
3402 skinframe->hasalpha = false;
3406 skinframe->base = ddsbase;
3407 skinframe->hasalpha = ddshasalpha;
3408 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3409 if (r_loadfog && skinframe->hasalpha)
3410 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);
3411 //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]);
3415 basepixels_width = image_width;
3416 basepixels_height = image_height;
3417 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);
3418 if (textureflags & TEXF_ALPHA)
3420 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3422 if (basepixels[j] < 255)
3424 skinframe->hasalpha = true;
3428 if (r_loadfog && skinframe->hasalpha)
3430 // has transparent pixels
3431 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3432 for (j = 0;j < image_width * image_height * 4;j += 4)
3437 pixels[j+3] = basepixels[j+3];
3439 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);
3443 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3445 //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]);
3446 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3447 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3448 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3449 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3455 mymiplevel = savemiplevel;
3456 if (r_loadnormalmap)
3457 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);
3458 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3460 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3461 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3462 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3463 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3466 // _norm is the name used by tenebrae and has been adopted as standard
3467 if (r_loadnormalmap && skinframe->nmap == NULL)
3469 mymiplevel = savemiplevel;
3470 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3472 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);
3476 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3478 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3479 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3480 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);
3482 Mem_Free(bumppixels);
3484 else if (r_shadow_bumpscale_basetexture.value > 0)
3486 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3487 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3488 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);
3492 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3493 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3497 // _luma is supported only for tenebrae compatibility
3498 // _glow is the preferred name
3499 mymiplevel = savemiplevel;
3500 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))))
3502 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);
3504 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3505 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3507 Mem_Free(pixels);pixels = NULL;
3510 mymiplevel = savemiplevel;
3511 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3513 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);
3515 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3516 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3522 mymiplevel = savemiplevel;
3523 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3525 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);
3527 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3528 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3534 mymiplevel = savemiplevel;
3535 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3537 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);
3539 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3540 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3546 mymiplevel = savemiplevel;
3547 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3549 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);
3551 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3552 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3559 Mem_Free(basepixels);
3564 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3565 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3568 unsigned char *temp1, *temp2;
3569 skinframe_t *skinframe;
3572 if (cls.state == ca_dedicated)
3575 // if already loaded just return it, otherwise make a new skinframe
3576 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3577 if (skinframe->base)
3579 textureflags &= ~TEXF_FORCE_RELOAD;
3581 skinframe->stain = NULL;
3582 skinframe->merged = NULL;
3583 skinframe->base = NULL;
3584 skinframe->pants = NULL;
3585 skinframe->shirt = NULL;
3586 skinframe->nmap = NULL;
3587 skinframe->gloss = NULL;
3588 skinframe->glow = NULL;
3589 skinframe->fog = NULL;
3590 skinframe->reflect = NULL;
3591 skinframe->hasalpha = false;
3593 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3597 if (developer_loading.integer)
3598 Con_Printf("loading 32bit skin \"%s\"\n", name);
3600 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3602 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3603 temp2 = temp1 + width * height * 4;
3604 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3605 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);
3608 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3609 if (textureflags & TEXF_ALPHA)
3611 for (i = 3;i < width * height * 4;i += 4)
3613 if (skindata[i] < 255)
3615 skinframe->hasalpha = true;
3619 if (r_loadfog && skinframe->hasalpha)
3621 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3622 memcpy(fogpixels, skindata, width * height * 4);
3623 for (i = 0;i < width * height * 4;i += 4)
3624 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3625 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3626 Mem_Free(fogpixels);
3630 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3631 //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]);
3636 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3640 skinframe_t *skinframe;
3642 if (cls.state == ca_dedicated)
3645 // if already loaded just return it, otherwise make a new skinframe
3646 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3647 if (skinframe->base)
3649 //textureflags &= ~TEXF_FORCE_RELOAD;
3651 skinframe->stain = NULL;
3652 skinframe->merged = NULL;
3653 skinframe->base = NULL;
3654 skinframe->pants = NULL;
3655 skinframe->shirt = NULL;
3656 skinframe->nmap = NULL;
3657 skinframe->gloss = NULL;
3658 skinframe->glow = NULL;
3659 skinframe->fog = NULL;
3660 skinframe->reflect = NULL;
3661 skinframe->hasalpha = false;
3663 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3667 if (developer_loading.integer)
3668 Con_Printf("loading quake skin \"%s\"\n", name);
3670 // 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)
3671 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3672 memcpy(skinframe->qpixels, skindata, width*height);
3673 skinframe->qwidth = width;
3674 skinframe->qheight = height;
3677 for (i = 0;i < width * height;i++)
3678 featuresmask |= palette_featureflags[skindata[i]];
3680 skinframe->hasalpha = false;
3681 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3682 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3683 skinframe->qgeneratemerged = true;
3684 skinframe->qgeneratebase = skinframe->qhascolormapping;
3685 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3687 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3688 //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]);
3693 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3697 unsigned char *skindata;
3700 if (!skinframe->qpixels)
3703 if (!skinframe->qhascolormapping)
3704 colormapped = false;
3708 if (!skinframe->qgeneratebase)
3713 if (!skinframe->qgeneratemerged)
3717 width = skinframe->qwidth;
3718 height = skinframe->qheight;
3719 skindata = skinframe->qpixels;
3721 if (skinframe->qgeneratenmap)
3723 unsigned char *temp1, *temp2;
3724 skinframe->qgeneratenmap = false;
3725 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3726 temp2 = temp1 + width * height * 4;
3727 // use either a custom palette or the quake palette
3728 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3729 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3730 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);
3734 if (skinframe->qgenerateglow)
3736 skinframe->qgenerateglow = false;
3737 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
3742 skinframe->qgeneratebase = false;
3743 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);
3744 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);
3745 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);
3749 skinframe->qgeneratemerged = false;
3750 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);
3753 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3755 Mem_Free(skinframe->qpixels);
3756 skinframe->qpixels = NULL;
3760 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)
3763 skinframe_t *skinframe;
3766 if (cls.state == ca_dedicated)
3769 // if already loaded just return it, otherwise make a new skinframe
3770 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3771 if (skinframe->base)
3773 textureflags &= ~TEXF_FORCE_RELOAD;
3775 skinframe->stain = NULL;
3776 skinframe->merged = NULL;
3777 skinframe->base = NULL;
3778 skinframe->pants = NULL;
3779 skinframe->shirt = NULL;
3780 skinframe->nmap = NULL;
3781 skinframe->gloss = NULL;
3782 skinframe->glow = NULL;
3783 skinframe->fog = NULL;
3784 skinframe->reflect = NULL;
3785 skinframe->hasalpha = false;
3787 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3791 if (developer_loading.integer)
3792 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3794 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3795 if (textureflags & TEXF_ALPHA)
3797 for (i = 0;i < width * height;i++)
3799 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3801 skinframe->hasalpha = true;
3805 if (r_loadfog && skinframe->hasalpha)
3806 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3809 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3810 //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]);
3815 skinframe_t *R_SkinFrame_LoadMissing(void)
3817 skinframe_t *skinframe;
3819 if (cls.state == ca_dedicated)
3822 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3823 skinframe->stain = NULL;
3824 skinframe->merged = NULL;
3825 skinframe->base = NULL;
3826 skinframe->pants = NULL;
3827 skinframe->shirt = NULL;
3828 skinframe->nmap = NULL;
3829 skinframe->gloss = NULL;
3830 skinframe->glow = NULL;
3831 skinframe->fog = NULL;
3832 skinframe->reflect = NULL;
3833 skinframe->hasalpha = false;
3835 skinframe->avgcolor[0] = rand() / RAND_MAX;
3836 skinframe->avgcolor[1] = rand() / RAND_MAX;
3837 skinframe->avgcolor[2] = rand() / RAND_MAX;
3838 skinframe->avgcolor[3] = 1;
3843 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3844 typedef struct suffixinfo_s
3847 qboolean flipx, flipy, flipdiagonal;
3850 static suffixinfo_t suffix[3][6] =
3853 {"px", false, false, false},
3854 {"nx", false, false, false},
3855 {"py", false, false, false},
3856 {"ny", false, false, false},
3857 {"pz", false, false, false},
3858 {"nz", false, false, false}
3861 {"posx", false, false, false},
3862 {"negx", false, false, false},
3863 {"posy", false, false, false},
3864 {"negy", false, false, false},
3865 {"posz", false, false, false},
3866 {"negz", false, false, false}
3869 {"rt", true, false, true},
3870 {"lf", false, true, true},
3871 {"ft", true, true, false},
3872 {"bk", false, false, false},
3873 {"up", true, false, true},
3874 {"dn", true, false, true}
3878 static int componentorder[4] = {0, 1, 2, 3};
3880 static rtexture_t *R_LoadCubemap(const char *basename)
3882 int i, j, cubemapsize;
3883 unsigned char *cubemappixels, *image_buffer;
3884 rtexture_t *cubemaptexture;
3886 // must start 0 so the first loadimagepixels has no requested width/height
3888 cubemappixels = NULL;
3889 cubemaptexture = NULL;
3890 // keep trying different suffix groups (posx, px, rt) until one loads
3891 for (j = 0;j < 3 && !cubemappixels;j++)
3893 // load the 6 images in the suffix group
3894 for (i = 0;i < 6;i++)
3896 // generate an image name based on the base and and suffix
3897 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3899 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3901 // an image loaded, make sure width and height are equal
3902 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3904 // if this is the first image to load successfully, allocate the cubemap memory
3905 if (!cubemappixels && image_width >= 1)
3907 cubemapsize = image_width;
3908 // note this clears to black, so unavailable sides are black
3909 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3911 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3913 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);
3916 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3918 Mem_Free(image_buffer);
3922 // if a cubemap loaded, upload it
3925 if (developer_loading.integer)
3926 Con_Printf("loading cubemap \"%s\"\n", basename);
3928 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);
3929 Mem_Free(cubemappixels);
3933 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3934 if (developer_loading.integer)
3936 Con_Printf("(tried tried images ");
3937 for (j = 0;j < 3;j++)
3938 for (i = 0;i < 6;i++)
3939 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3940 Con_Print(" and was unable to find any of them).\n");
3943 return cubemaptexture;
3946 rtexture_t *R_GetCubemap(const char *basename)
3949 for (i = 0;i < r_texture_numcubemaps;i++)
3950 if (r_texture_cubemaps[i] != NULL)
3951 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3952 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3953 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3954 return r_texture_whitecube;
3955 r_texture_numcubemaps++;
3956 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3957 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3958 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3959 return r_texture_cubemaps[i]->texture;
3962 static void R_Main_FreeViewCache(void)
3964 if (r_refdef.viewcache.entityvisible)
3965 Mem_Free(r_refdef.viewcache.entityvisible);
3966 if (r_refdef.viewcache.world_pvsbits)
3967 Mem_Free(r_refdef.viewcache.world_pvsbits);
3968 if (r_refdef.viewcache.world_leafvisible)
3969 Mem_Free(r_refdef.viewcache.world_leafvisible);
3970 if (r_refdef.viewcache.world_surfacevisible)
3971 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3972 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3975 static void R_Main_ResizeViewCache(void)
3977 int numentities = r_refdef.scene.numentities;
3978 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3979 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3980 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3981 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3982 if (r_refdef.viewcache.maxentities < numentities)
3984 r_refdef.viewcache.maxentities = numentities;
3985 if (r_refdef.viewcache.entityvisible)
3986 Mem_Free(r_refdef.viewcache.entityvisible);
3987 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3989 if (r_refdef.viewcache.world_numclusters != numclusters)
3991 r_refdef.viewcache.world_numclusters = numclusters;
3992 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3993 if (r_refdef.viewcache.world_pvsbits)
3994 Mem_Free(r_refdef.viewcache.world_pvsbits);
3995 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3997 if (r_refdef.viewcache.world_numleafs != numleafs)
3999 r_refdef.viewcache.world_numleafs = numleafs;
4000 if (r_refdef.viewcache.world_leafvisible)
4001 Mem_Free(r_refdef.viewcache.world_leafvisible);
4002 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4004 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4006 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4007 if (r_refdef.viewcache.world_surfacevisible)
4008 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4009 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4013 extern rtexture_t *loadingscreentexture;
4014 static void gl_main_start(void)
4016 loadingscreentexture = NULL;
4017 r_texture_blanknormalmap = NULL;
4018 r_texture_white = NULL;
4019 r_texture_grey128 = NULL;
4020 r_texture_black = NULL;
4021 r_texture_whitecube = NULL;
4022 r_texture_normalizationcube = NULL;
4023 r_texture_fogattenuation = NULL;
4024 r_texture_fogheighttexture = NULL;
4025 r_texture_gammaramps = NULL;
4026 r_texture_numcubemaps = 0;
4027 r_uniformbufferalignment = 32;
4029 r_loaddds = r_texture_dds_load.integer != 0;
4030 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4032 switch(vid.renderpath)
4034 case RENDERPATH_GL20:
4035 case RENDERPATH_D3D9:
4036 case RENDERPATH_D3D10:
4037 case RENDERPATH_D3D11:
4038 case RENDERPATH_SOFT:
4039 case RENDERPATH_GLES2:
4040 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4041 Cvar_SetValueQuick(&gl_combine, 1);
4042 Cvar_SetValueQuick(&r_glsl, 1);
4043 r_loadnormalmap = true;
4046 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4047 if (vid.support.arb_uniform_buffer_object)
4048 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4051 case RENDERPATH_GL13:
4052 case RENDERPATH_GLES1:
4053 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4054 Cvar_SetValueQuick(&gl_combine, 1);
4055 Cvar_SetValueQuick(&r_glsl, 0);
4056 r_loadnormalmap = false;
4057 r_loadgloss = false;
4060 case RENDERPATH_GL11:
4061 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4062 Cvar_SetValueQuick(&gl_combine, 0);
4063 Cvar_SetValueQuick(&r_glsl, 0);
4064 r_loadnormalmap = false;
4065 r_loadgloss = false;
4071 R_FrameData_Reset();
4072 R_BufferData_Reset();
4076 memset(r_queries, 0, sizeof(r_queries));
4078 r_qwskincache = NULL;
4079 r_qwskincache_size = 0;
4081 // due to caching of texture_t references, the collision cache must be reset
4082 Collision_Cache_Reset(true);
4084 // set up r_skinframe loading system for textures
4085 memset(&r_skinframe, 0, sizeof(r_skinframe));
4086 r_skinframe.loadsequence = 1;
4087 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4089 r_main_texturepool = R_AllocTexturePool();
4090 R_BuildBlankTextures();
4092 if (vid.support.arb_texture_cube_map)
4095 R_BuildNormalizationCube();
4097 r_texture_fogattenuation = NULL;
4098 r_texture_fogheighttexture = NULL;
4099 r_texture_gammaramps = NULL;
4100 //r_texture_fogintensity = NULL;
4101 memset(&r_fb, 0, sizeof(r_fb));
4102 r_glsl_permutation = NULL;
4103 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4104 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4105 glslshaderstring = NULL;
4107 r_hlsl_permutation = NULL;
4108 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4109 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4111 hlslshaderstring = NULL;
4112 memset(&r_svbsp, 0, sizeof (r_svbsp));
4114 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4115 r_texture_numcubemaps = 0;
4117 r_refdef.fogmasktable_density = 0;
4120 // For Steelstorm Android
4121 // FIXME CACHE the program and reload
4122 // FIXME see possible combinations for SS:BR android
4123 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4124 R_SetupShader_SetPermutationGLSL(0, 12);
4125 R_SetupShader_SetPermutationGLSL(0, 13);
4126 R_SetupShader_SetPermutationGLSL(0, 8388621);
4127 R_SetupShader_SetPermutationGLSL(3, 0);
4128 R_SetupShader_SetPermutationGLSL(3, 2048);
4129 R_SetupShader_SetPermutationGLSL(5, 0);
4130 R_SetupShader_SetPermutationGLSL(5, 2);
4131 R_SetupShader_SetPermutationGLSL(5, 2048);
4132 R_SetupShader_SetPermutationGLSL(5, 8388608);
4133 R_SetupShader_SetPermutationGLSL(11, 1);
4134 R_SetupShader_SetPermutationGLSL(11, 2049);
4135 R_SetupShader_SetPermutationGLSL(11, 8193);
4136 R_SetupShader_SetPermutationGLSL(11, 10241);
4137 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4141 static void gl_main_shutdown(void)
4144 R_FrameData_Reset();
4145 R_BufferData_Reset();
4147 R_Main_FreeViewCache();
4149 switch(vid.renderpath)
4151 case RENDERPATH_GL11:
4152 case RENDERPATH_GL13:
4153 case RENDERPATH_GL20:
4154 case RENDERPATH_GLES1:
4155 case RENDERPATH_GLES2:
4156 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4158 qglDeleteQueriesARB(r_maxqueries, r_queries);
4161 case RENDERPATH_D3D9:
4162 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4164 case RENDERPATH_D3D10:
4165 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4167 case RENDERPATH_D3D11:
4168 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4170 case RENDERPATH_SOFT:
4176 memset(r_queries, 0, sizeof(r_queries));
4178 r_qwskincache = NULL;
4179 r_qwskincache_size = 0;
4181 // clear out the r_skinframe state
4182 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4183 memset(&r_skinframe, 0, sizeof(r_skinframe));
4186 Mem_Free(r_svbsp.nodes);
4187 memset(&r_svbsp, 0, sizeof (r_svbsp));
4188 R_FreeTexturePool(&r_main_texturepool);
4189 loadingscreentexture = NULL;
4190 r_texture_blanknormalmap = NULL;
4191 r_texture_white = NULL;
4192 r_texture_grey128 = NULL;
4193 r_texture_black = NULL;
4194 r_texture_whitecube = NULL;
4195 r_texture_normalizationcube = NULL;
4196 r_texture_fogattenuation = NULL;
4197 r_texture_fogheighttexture = NULL;
4198 r_texture_gammaramps = NULL;
4199 r_texture_numcubemaps = 0;
4200 //r_texture_fogintensity = NULL;
4201 memset(&r_fb, 0, sizeof(r_fb));
4204 r_glsl_permutation = NULL;
4205 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4206 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4207 glslshaderstring = NULL;
4209 r_hlsl_permutation = NULL;
4210 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4211 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4213 hlslshaderstring = NULL;
4216 static void gl_main_newmap(void)
4218 // FIXME: move this code to client
4219 char *entities, entname[MAX_QPATH];
4221 Mem_Free(r_qwskincache);
4222 r_qwskincache = NULL;
4223 r_qwskincache_size = 0;
4226 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4227 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4229 CL_ParseEntityLump(entities);
4233 if (cl.worldmodel->brush.entities)
4234 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4236 R_Main_FreeViewCache();
4238 R_FrameData_Reset();
4239 R_BufferData_Reset();
4242 void GL_Main_Init(void)
4245 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4247 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4248 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4249 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4250 if (gamemode == GAME_NEHAHRA)
4252 Cvar_RegisterVariable (&gl_fogenable);
4253 Cvar_RegisterVariable (&gl_fogdensity);
4254 Cvar_RegisterVariable (&gl_fogred);
4255 Cvar_RegisterVariable (&gl_foggreen);
4256 Cvar_RegisterVariable (&gl_fogblue);
4257 Cvar_RegisterVariable (&gl_fogstart);
4258 Cvar_RegisterVariable (&gl_fogend);
4259 Cvar_RegisterVariable (&gl_skyclip);
4261 Cvar_RegisterVariable(&r_motionblur);
4262 Cvar_RegisterVariable(&r_damageblur);
4263 Cvar_RegisterVariable(&r_motionblur_averaging);
4264 Cvar_RegisterVariable(&r_motionblur_randomize);
4265 Cvar_RegisterVariable(&r_motionblur_minblur);
4266 Cvar_RegisterVariable(&r_motionblur_maxblur);
4267 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4268 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4269 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4270 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4271 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4272 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4273 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4274 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4275 Cvar_RegisterVariable(&r_equalize_entities_by);
4276 Cvar_RegisterVariable(&r_equalize_entities_to);
4277 Cvar_RegisterVariable(&r_depthfirst);
4278 Cvar_RegisterVariable(&r_useinfinitefarclip);
4279 Cvar_RegisterVariable(&r_farclip_base);
4280 Cvar_RegisterVariable(&r_farclip_world);
4281 Cvar_RegisterVariable(&r_nearclip);
4282 Cvar_RegisterVariable(&r_deformvertexes);
4283 Cvar_RegisterVariable(&r_transparent);
4284 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4285 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4286 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4287 Cvar_RegisterVariable(&r_showoverdraw);
4288 Cvar_RegisterVariable(&r_showbboxes);
4289 Cvar_RegisterVariable(&r_showsurfaces);
4290 Cvar_RegisterVariable(&r_showtris);
4291 Cvar_RegisterVariable(&r_shownormals);
4292 Cvar_RegisterVariable(&r_showlighting);
4293 Cvar_RegisterVariable(&r_showshadowvolumes);
4294 Cvar_RegisterVariable(&r_showcollisionbrushes);
4295 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4296 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4297 Cvar_RegisterVariable(&r_showdisabledepthtest);
4298 Cvar_RegisterVariable(&r_drawportals);
4299 Cvar_RegisterVariable(&r_drawentities);
4300 Cvar_RegisterVariable(&r_draw2d);
4301 Cvar_RegisterVariable(&r_drawworld);
4302 Cvar_RegisterVariable(&r_cullentities_trace);
4303 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4304 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4305 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4306 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4307 Cvar_RegisterVariable(&r_sortentities);
4308 Cvar_RegisterVariable(&r_drawviewmodel);
4309 Cvar_RegisterVariable(&r_drawexteriormodel);
4310 Cvar_RegisterVariable(&r_speeds);
4311 Cvar_RegisterVariable(&r_fullbrights);
4312 Cvar_RegisterVariable(&r_wateralpha);
4313 Cvar_RegisterVariable(&r_dynamic);
4314 Cvar_RegisterVariable(&r_fakelight);
4315 Cvar_RegisterVariable(&r_fakelight_intensity);
4316 Cvar_RegisterVariable(&r_fullbright);
4317 Cvar_RegisterVariable(&r_shadows);
4318 Cvar_RegisterVariable(&r_shadows_darken);
4319 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4320 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4321 Cvar_RegisterVariable(&r_shadows_throwdistance);
4322 Cvar_RegisterVariable(&r_shadows_throwdirection);
4323 Cvar_RegisterVariable(&r_shadows_focus);
4324 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4325 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4326 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4327 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4328 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4329 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4330 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4331 Cvar_RegisterVariable(&r_fog_exp2);
4332 Cvar_RegisterVariable(&r_fog_clear);
4333 Cvar_RegisterVariable(&r_drawfog);
4334 Cvar_RegisterVariable(&r_transparentdepthmasking);
4335 Cvar_RegisterVariable(&r_transparent_sortmindist);
4336 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4337 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4338 Cvar_RegisterVariable(&r_texture_dds_load);
4339 Cvar_RegisterVariable(&r_texture_dds_save);
4340 Cvar_RegisterVariable(&r_textureunits);
4341 Cvar_RegisterVariable(&gl_combine);
4342 Cvar_RegisterVariable(&r_usedepthtextures);
4343 Cvar_RegisterVariable(&r_viewfbo);
4344 Cvar_RegisterVariable(&r_viewscale);
4345 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4346 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4347 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4348 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4349 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4350 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4351 Cvar_RegisterVariable(&r_glsl);
4352 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4353 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4354 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4355 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4356 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4357 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4358 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4359 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4360 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4361 Cvar_RegisterVariable(&r_glsl_postprocess);
4362 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4363 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4364 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4365 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4366 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4367 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4368 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4369 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4370 Cvar_RegisterVariable(&r_celshading);
4371 Cvar_RegisterVariable(&r_celoutlines);
4373 Cvar_RegisterVariable(&r_water);
4374 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4375 Cvar_RegisterVariable(&r_water_clippingplanebias);
4376 Cvar_RegisterVariable(&r_water_refractdistort);
4377 Cvar_RegisterVariable(&r_water_reflectdistort);
4378 Cvar_RegisterVariable(&r_water_scissormode);
4379 Cvar_RegisterVariable(&r_water_lowquality);
4380 Cvar_RegisterVariable(&r_water_hideplayer);
4381 Cvar_RegisterVariable(&r_water_fbo);
4383 Cvar_RegisterVariable(&r_lerpsprites);
4384 Cvar_RegisterVariable(&r_lerpmodels);
4385 Cvar_RegisterVariable(&r_lerplightstyles);
4386 Cvar_RegisterVariable(&r_waterscroll);
4387 Cvar_RegisterVariable(&r_bloom);
4388 Cvar_RegisterVariable(&r_bloom_colorscale);
4389 Cvar_RegisterVariable(&r_bloom_brighten);
4390 Cvar_RegisterVariable(&r_bloom_blur);
4391 Cvar_RegisterVariable(&r_bloom_resolution);
4392 Cvar_RegisterVariable(&r_bloom_colorexponent);
4393 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4394 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4395 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4396 Cvar_RegisterVariable(&r_hdr_glowintensity);
4397 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4398 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4399 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4400 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4401 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4402 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4403 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4404 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4405 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4406 Cvar_RegisterVariable(&developer_texturelogging);
4407 Cvar_RegisterVariable(&gl_lightmaps);
4408 Cvar_RegisterVariable(&r_test);
4409 Cvar_RegisterVariable(&r_batch_multidraw);
4410 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4411 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4412 Cvar_RegisterVariable(&r_glsl_skeletal);
4413 Cvar_RegisterVariable(&r_glsl_saturation);
4414 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4415 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4416 Cvar_RegisterVariable(&r_framedatasize);
4417 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4418 Cvar_RegisterVariable(&r_buffermegs[i]);
4419 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4420 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4421 Cvar_SetValue("r_fullbrights", 0);
4422 #ifdef DP_MOBILETOUCH
4423 // GLES devices have terrible depth precision in general, so...
4424 Cvar_SetValueQuick(&r_nearclip, 4);
4425 Cvar_SetValueQuick(&r_farclip_base, 4096);
4426 Cvar_SetValueQuick(&r_farclip_world, 0);
4427 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4429 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4432 void Render_Init(void)
4445 R_LightningBeams_Init();
4455 extern char *ENGINE_EXTENSIONS;
4458 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4459 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4460 gl_version = (const char *)qglGetString(GL_VERSION);
4461 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4465 if (!gl_platformextensions)
4466 gl_platformextensions = "";
4468 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4469 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4470 Con_Printf("GL_VERSION: %s\n", gl_version);
4471 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4472 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4474 VID_CheckExtensions();
4476 // LordHavoc: report supported extensions
4478 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4480 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4483 // clear to black (loading plaque will be seen over this)
4484 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4488 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4492 if (r_trippy.integer)
4494 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4496 p = r_refdef.view.frustum + i;
4501 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4505 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4509 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4513 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4517 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4521 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4525 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4529 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4537 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4541 if (r_trippy.integer)
4543 for (i = 0;i < numplanes;i++)
4550 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4554 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4558 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4562 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4566 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4570 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4574 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4578 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4586 //==================================================================================
4588 // LordHavoc: this stores temporary data used within the same frame
4590 typedef struct r_framedata_mem_s
4592 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4593 size_t size; // how much usable space
4594 size_t current; // how much space in use
4595 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4596 size_t wantedsize; // how much space was allocated
4597 unsigned char *data; // start of real data (16byte aligned)
4601 static r_framedata_mem_t *r_framedata_mem;
4603 void R_FrameData_Reset(void)
4605 while (r_framedata_mem)
4607 r_framedata_mem_t *next = r_framedata_mem->purge;
4608 Mem_Free(r_framedata_mem);
4609 r_framedata_mem = next;
4613 static void R_FrameData_Resize(qboolean mustgrow)
4616 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4617 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4618 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4620 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4621 newmem->wantedsize = wantedsize;
4622 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4623 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4624 newmem->current = 0;
4626 newmem->purge = r_framedata_mem;
4627 r_framedata_mem = newmem;
4631 void R_FrameData_NewFrame(void)
4633 R_FrameData_Resize(false);
4634 if (!r_framedata_mem)
4636 // if we ran out of space on the last frame, free the old memory now
4637 while (r_framedata_mem->purge)
4639 // repeatedly remove the second item in the list, leaving only head
4640 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4641 Mem_Free(r_framedata_mem->purge);
4642 r_framedata_mem->purge = next;
4644 // reset the current mem pointer
4645 r_framedata_mem->current = 0;
4646 r_framedata_mem->mark = 0;
4649 void *R_FrameData_Alloc(size_t size)
4654 // align to 16 byte boundary - the data pointer is already aligned, so we
4655 // only need to ensure the size of every allocation is also aligned
4656 size = (size + 15) & ~15;
4658 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4660 // emergency - we ran out of space, allocate more memory
4661 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4662 // this might not be a growing it, but we'll allocate another buffer every time
4663 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4664 R_FrameData_Resize(true);
4667 data = r_framedata_mem->data + r_framedata_mem->current;
4668 r_framedata_mem->current += size;
4670 // count the usage for stats
4671 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4672 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4674 return (void *)data;
4677 void *R_FrameData_Store(size_t size, void *data)
4679 void *d = R_FrameData_Alloc(size);
4681 memcpy(d, data, size);
4685 void R_FrameData_SetMark(void)
4687 if (!r_framedata_mem)
4689 r_framedata_mem->mark = r_framedata_mem->current;
4692 void R_FrameData_ReturnToMark(void)
4694 if (!r_framedata_mem)
4696 r_framedata_mem->current = r_framedata_mem->mark;
4699 //==================================================================================
4701 // avoid reusing the same buffer objects on consecutive frames
4702 #define R_BUFFERDATA_CYCLE 3
4704 typedef struct r_bufferdata_buffer_s
4706 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4707 size_t size; // how much usable space
4708 size_t current; // how much space in use
4709 r_meshbuffer_t *buffer; // the buffer itself
4711 r_bufferdata_buffer_t;
4713 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4714 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4716 /// frees all dynamic buffers
4717 void R_BufferData_Reset(void)
4720 r_bufferdata_buffer_t **p, *mem;
4721 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4723 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4726 p = &r_bufferdata_buffer[cycle][type];
4732 R_Mesh_DestroyMeshBuffer(mem->buffer);
4739 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4740 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4742 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4744 float newvalue = r_buffermegs[type].value;
4746 // increase the cvar if we have to (but only if we already have a mem)
4747 if (mustgrow && mem)
4749 newvalue = bound(0.25f, newvalue, 256.0f);
4750 while (newvalue * 1024*1024 < minsize)
4753 // clamp the cvar to valid range
4754 newvalue = bound(0.25f, newvalue, 256.0f);
4755 if (r_buffermegs[type].value != newvalue)
4756 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4758 // calculate size in bytes
4759 size = (size_t)(newvalue * 1024*1024);
4760 size = bound(131072, size, 256*1024*1024);
4762 // allocate a new buffer if the size is different (purge old one later)
4763 // or if we were told we must grow the buffer
4764 if (!mem || mem->size != size || mustgrow)
4766 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4769 if (type == R_BUFFERDATA_VERTEX)
4770 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4771 else if (type == R_BUFFERDATA_INDEX16)
4772 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4773 else if (type == R_BUFFERDATA_INDEX32)
4774 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4775 else if (type == R_BUFFERDATA_UNIFORM)
4776 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4777 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4778 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4782 void R_BufferData_NewFrame(void)
4785 r_bufferdata_buffer_t **p, *mem;
4786 // cycle to the next frame's buffers
4787 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4788 // if we ran out of space on the last time we used these buffers, free the old memory now
4789 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4791 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4793 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4794 // free all but the head buffer, this is how we recycle obsolete
4795 // buffers after they are no longer in use
4796 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4802 R_Mesh_DestroyMeshBuffer(mem->buffer);
4805 // reset the current offset
4806 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4811 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4813 r_bufferdata_buffer_t *mem;
4817 *returnbufferoffset = 0;
4819 // align size to a byte boundary appropriate for the buffer type, this
4820 // makes all allocations have aligned start offsets
4821 if (type == R_BUFFERDATA_UNIFORM)
4822 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4824 padsize = (datasize + 15) & ~15;
4826 // if we ran out of space in this buffer we must allocate a new one
4827 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)
4828 R_BufferData_Resize(type, true, padsize);
4830 // if the resize did not give us enough memory, fail
4831 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4832 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4834 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4835 offset = mem->current;
4836 mem->current += padsize;
4838 // upload the data to the buffer at the chosen offset
4840 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4841 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4843 // count the usage for stats
4844 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4845 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4847 // return the buffer offset
4848 *returnbufferoffset = offset;
4853 //==================================================================================
4855 // LordHavoc: animcache originally written by Echon, rewritten since then
4858 * Animation cache prevents re-generating mesh data for an animated model
4859 * multiple times in one frame for lighting, shadowing, reflections, etc.
4862 void R_AnimCache_Free(void)
4866 void R_AnimCache_ClearCache(void)
4869 entity_render_t *ent;
4871 for (i = 0;i < r_refdef.scene.numentities;i++)
4873 ent = r_refdef.scene.entities[i];
4874 ent->animcache_vertex3f = NULL;
4875 ent->animcache_vertex3f_vertexbuffer = NULL;
4876 ent->animcache_vertex3f_bufferoffset = 0;
4877 ent->animcache_normal3f = NULL;
4878 ent->animcache_normal3f_vertexbuffer = NULL;
4879 ent->animcache_normal3f_bufferoffset = 0;
4880 ent->animcache_svector3f = NULL;
4881 ent->animcache_svector3f_vertexbuffer = NULL;
4882 ent->animcache_svector3f_bufferoffset = 0;
4883 ent->animcache_tvector3f = NULL;
4884 ent->animcache_tvector3f_vertexbuffer = NULL;
4885 ent->animcache_tvector3f_bufferoffset = 0;
4886 ent->animcache_vertexmesh = NULL;
4887 ent->animcache_vertexmesh_vertexbuffer = NULL;
4888 ent->animcache_vertexmesh_bufferoffset = 0;
4889 ent->animcache_skeletaltransform3x4 = NULL;
4890 ent->animcache_skeletaltransform3x4buffer = NULL;
4891 ent->animcache_skeletaltransform3x4offset = 0;
4892 ent->animcache_skeletaltransform3x4size = 0;
4896 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4900 // check if we need the meshbuffers
4901 if (!vid.useinterleavedarrays)
4904 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4905 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4906 // TODO: upload vertexbuffer?
4907 if (ent->animcache_vertexmesh)
4909 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4910 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4911 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4912 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4913 for (i = 0;i < numvertices;i++)
4914 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4915 if (ent->animcache_svector3f)
4916 for (i = 0;i < numvertices;i++)
4917 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4918 if (ent->animcache_tvector3f)
4919 for (i = 0;i < numvertices;i++)
4920 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4921 if (ent->animcache_normal3f)
4922 for (i = 0;i < numvertices;i++)
4923 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4927 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4929 dp_model_t *model = ent->model;
4932 // see if this ent is worth caching
4933 if (!model || !model->Draw || !model->AnimateVertices)
4935 // nothing to cache if it contains no animations and has no skeleton
4936 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4938 // see if it is already cached for gpuskeletal
4939 if (ent->animcache_skeletaltransform3x4)
4941 // see if it is already cached as a mesh
4942 if (ent->animcache_vertex3f)
4944 // check if we need to add normals or tangents
4945 if (ent->animcache_normal3f)
4946 wantnormals = false;
4947 if (ent->animcache_svector3f)
4948 wanttangents = false;
4949 if (!wantnormals && !wanttangents)
4953 // check which kind of cache we need to generate
4954 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4956 // cache the skeleton so the vertex shader can use it
4957 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4958 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4959 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4960 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4961 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4962 // note: this can fail if the buffer is at the grow limit
4963 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4964 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4966 else if (ent->animcache_vertex3f)
4968 // mesh was already cached but we may need to add normals/tangents
4969 // (this only happens with multiple views, reflections, cameras, etc)
4970 if (wantnormals || wanttangents)
4972 numvertices = model->surfmesh.num_vertices;
4974 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4977 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4978 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4980 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4981 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4982 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4983 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4984 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4989 // generate mesh cache
4990 numvertices = model->surfmesh.num_vertices;
4991 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4993 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4996 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4997 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4999 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5000 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5001 if (wantnormals || wanttangents)
5003 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5004 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5005 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5007 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5008 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5009 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5014 void R_AnimCache_CacheVisibleEntities(void)
5017 qboolean wantnormals = true;
5018 qboolean wanttangents = !r_showsurfaces.integer;
5020 switch(vid.renderpath)
5022 case RENDERPATH_GL20:
5023 case RENDERPATH_D3D9:
5024 case RENDERPATH_D3D10:
5025 case RENDERPATH_D3D11:
5026 case RENDERPATH_GLES2:
5028 case RENDERPATH_GL11:
5029 case RENDERPATH_GL13:
5030 case RENDERPATH_GLES1:
5031 wanttangents = false;
5033 case RENDERPATH_SOFT:
5037 if (r_shownormals.integer)
5038 wanttangents = wantnormals = true;
5040 // TODO: thread this
5041 // NOTE: R_PrepareRTLights() also caches entities
5043 for (i = 0;i < r_refdef.scene.numentities;i++)
5044 if (r_refdef.viewcache.entityvisible[i])
5045 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5048 //==================================================================================
5050 extern cvar_t r_overheadsprites_pushback;
5052 static void R_View_UpdateEntityLighting (void)
5055 entity_render_t *ent;
5056 vec3_t tempdiffusenormal, avg;
5057 vec_t f, fa, fd, fdd;
5058 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5060 for (i = 0;i < r_refdef.scene.numentities;i++)
5062 ent = r_refdef.scene.entities[i];
5064 // skip unseen models
5065 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5069 if (ent->model && ent->model == cl.worldmodel)
5071 // TODO: use modellight for r_ambient settings on world?
5072 VectorSet(ent->modellight_ambient, 0, 0, 0);
5073 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5074 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5078 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5080 // aleady updated by CSQC
5081 // TODO: force modellight on BSP models in this case?
5082 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5086 // fetch the lighting from the worldmodel data
5087 VectorClear(ent->modellight_ambient);
5088 VectorClear(ent->modellight_diffuse);
5089 VectorClear(tempdiffusenormal);
5090 if (ent->flags & RENDER_LIGHT)
5093 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5095 // complete lightning for lit sprites
5096 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5097 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5099 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5100 org[2] = org[2] + r_overheadsprites_pushback.value;
5101 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5104 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5106 if(ent->flags & RENDER_EQUALIZE)
5108 // first fix up ambient lighting...
5109 if(r_equalize_entities_minambient.value > 0)
5111 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5114 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5115 if(fa < r_equalize_entities_minambient.value * fd)
5118 // fa'/fd' = minambient
5119 // fa'+0.25*fd' = fa+0.25*fd
5121 // fa' = fd' * minambient
5122 // fd'*(0.25+minambient) = fa+0.25*fd
5124 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5125 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5127 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5128 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
5129 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5130 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5135 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5137 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5138 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5142 // adjust brightness and saturation to target
5143 avg[0] = avg[1] = avg[2] = fa / f;
5144 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5145 avg[0] = avg[1] = avg[2] = fd / f;
5146 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5152 VectorSet(ent->modellight_ambient, 1, 1, 1);
5155 // move the light direction into modelspace coordinates for lighting code
5156 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5157 if(VectorLength2(ent->modellight_lightdir) == 0)
5158 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5159 VectorNormalize(ent->modellight_lightdir);
5163 #define MAX_LINEOFSIGHTTRACES 64
5165 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5168 vec3_t boxmins, boxmaxs;
5171 dp_model_t *model = r_refdef.scene.worldmodel;
5173 if (!model || !model->brush.TraceLineOfSight)
5176 // expand the box a little
5177 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5178 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5179 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5180 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5181 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5182 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5184 // return true if eye is inside enlarged box
5185 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5189 VectorCopy(eye, start);
5190 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5191 if (model->brush.TraceLineOfSight(model, start, end))
5194 // try various random positions
5195 for (i = 0;i < numsamples;i++)
5197 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5198 if (model->brush.TraceLineOfSight(model, start, end))
5206 static void R_View_UpdateEntityVisible (void)
5211 entity_render_t *ent;
5213 if (r_refdef.envmap || r_fb.water.hideplayer)
5214 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5215 else if (chase_active.integer || r_fb.water.renderingscene)
5216 renderimask = RENDER_VIEWMODEL;
5218 renderimask = RENDER_EXTERIORMODEL;
5219 if (!r_drawviewmodel.integer)
5220 renderimask |= RENDER_VIEWMODEL;
5221 if (!r_drawexteriormodel.integer)
5222 renderimask |= RENDER_EXTERIORMODEL;
5223 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5224 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5226 // worldmodel can check visibility
5227 for (i = 0;i < r_refdef.scene.numentities;i++)
5229 ent = r_refdef.scene.entities[i];
5230 if (!(ent->flags & renderimask))
5231 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)))
5232 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))
5233 r_refdef.viewcache.entityvisible[i] = true;
5238 // no worldmodel or it can't check visibility
5239 for (i = 0;i < r_refdef.scene.numentities;i++)
5241 ent = r_refdef.scene.entities[i];
5242 if (!(ent->flags & renderimask))
5243 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)))
5244 r_refdef.viewcache.entityvisible[i] = true;
5247 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5248 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5250 for (i = 0;i < r_refdef.scene.numentities;i++)
5252 if (!r_refdef.viewcache.entityvisible[i])
5254 ent = r_refdef.scene.entities[i];
5255 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5257 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5259 continue; // temp entities do pvs only
5260 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5261 ent->last_trace_visibility = realtime;
5262 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5263 r_refdef.viewcache.entityvisible[i] = 0;
5269 /// only used if skyrendermasked, and normally returns false
5270 static int R_DrawBrushModelsSky (void)
5273 entity_render_t *ent;
5276 for (i = 0;i < r_refdef.scene.numentities;i++)
5278 if (!r_refdef.viewcache.entityvisible[i])
5280 ent = r_refdef.scene.entities[i];
5281 if (!ent->model || !ent->model->DrawSky)
5283 ent->model->DrawSky(ent);
5289 static void R_DrawNoModel(entity_render_t *ent);
5290 static void R_DrawModels(void)
5293 entity_render_t *ent;
5295 for (i = 0;i < r_refdef.scene.numentities;i++)
5297 if (!r_refdef.viewcache.entityvisible[i])
5299 ent = r_refdef.scene.entities[i];
5300 r_refdef.stats[r_stat_entities]++;
5302 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5305 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5306 Con_Printf("R_DrawModels\n");
5307 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]);
5308 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);
5309 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);
5312 if (ent->model && ent->model->Draw != NULL)
5313 ent->model->Draw(ent);
5319 static void R_DrawModelsDepth(void)
5322 entity_render_t *ent;
5324 for (i = 0;i < r_refdef.scene.numentities;i++)
5326 if (!r_refdef.viewcache.entityvisible[i])
5328 ent = r_refdef.scene.entities[i];
5329 if (ent->model && ent->model->DrawDepth != NULL)
5330 ent->model->DrawDepth(ent);
5334 static void R_DrawModelsDebug(void)
5337 entity_render_t *ent;
5339 for (i = 0;i < r_refdef.scene.numentities;i++)
5341 if (!r_refdef.viewcache.entityvisible[i])
5343 ent = r_refdef.scene.entities[i];
5344 if (ent->model && ent->model->DrawDebug != NULL)
5345 ent->model->DrawDebug(ent);
5349 static void R_DrawModelsAddWaterPlanes(void)
5352 entity_render_t *ent;
5354 for (i = 0;i < r_refdef.scene.numentities;i++)
5356 if (!r_refdef.viewcache.entityvisible[i])
5358 ent = r_refdef.scene.entities[i];
5359 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5360 ent->model->DrawAddWaterPlanes(ent);
5364 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}};
5366 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5368 if (r_hdr_irisadaptation.integer)
5373 vec3_t diffusenormal;
5375 vec_t brightness = 0.0f;
5380 VectorCopy(r_refdef.view.forward, forward);
5381 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5383 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5384 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5385 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5386 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5387 d = DotProduct(forward, diffusenormal);
5388 brightness += VectorLength(ambient);
5390 brightness += d * VectorLength(diffuse);
5392 brightness *= 1.0f / c;
5393 brightness += 0.00001f; // make sure it's never zero
5394 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5395 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5396 current = r_hdr_irisadaptation_value.value;
5398 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5399 else if (current > goal)
5400 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5401 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5402 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5404 else if (r_hdr_irisadaptation_value.value != 1.0f)
5405 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5408 static void R_View_SetFrustum(const int *scissor)
5411 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5412 vec3_t forward, left, up, origin, v;
5416 // flipped x coordinates (because x points left here)
5417 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5418 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5420 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5421 switch(vid.renderpath)
5423 case RENDERPATH_D3D9:
5424 case RENDERPATH_D3D10:
5425 case RENDERPATH_D3D11:
5426 // non-flipped y coordinates
5427 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5428 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5430 case RENDERPATH_SOFT:
5431 case RENDERPATH_GL11:
5432 case RENDERPATH_GL13:
5433 case RENDERPATH_GL20:
5434 case RENDERPATH_GLES1:
5435 case RENDERPATH_GLES2:
5436 // non-flipped y coordinates
5437 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5438 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5443 // we can't trust r_refdef.view.forward and friends in reflected scenes
5444 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5447 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5448 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5449 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5450 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5451 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5452 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5453 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5454 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5455 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5456 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5457 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5458 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5462 zNear = r_refdef.nearclip;
5463 nudge = 1.0 - 1.0 / (1<<23);
5464 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5465 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5466 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5467 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5468 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5469 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5470 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5471 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5477 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5478 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5479 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5480 r_refdef.view.frustum[0].dist = m[15] - m[12];
5482 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5483 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5484 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5485 r_refdef.view.frustum[1].dist = m[15] + m[12];
5487 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5488 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5489 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5490 r_refdef.view.frustum[2].dist = m[15] - m[13];
5492 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5493 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5494 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5495 r_refdef.view.frustum[3].dist = m[15] + m[13];
5497 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5498 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5499 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5500 r_refdef.view.frustum[4].dist = m[15] - m[14];
5502 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5503 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5504 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5505 r_refdef.view.frustum[5].dist = m[15] + m[14];
5508 if (r_refdef.view.useperspective)
5510 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5511 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]);
5512 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]);
5513 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]);
5514 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]);
5516 // then the normals from the corners relative to origin
5517 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5518 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5519 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5520 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5522 // in a NORMAL view, forward cross left == up
5523 // in a REFLECTED view, forward cross left == down
5524 // so our cross products above need to be adjusted for a left handed coordinate system
5525 CrossProduct(forward, left, v);
5526 if(DotProduct(v, up) < 0)
5528 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5529 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5530 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5531 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5534 // Leaving those out was a mistake, those were in the old code, and they
5535 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5536 // I couldn't reproduce it after adding those normalizations. --blub
5537 VectorNormalize(r_refdef.view.frustum[0].normal);
5538 VectorNormalize(r_refdef.view.frustum[1].normal);
5539 VectorNormalize(r_refdef.view.frustum[2].normal);
5540 VectorNormalize(r_refdef.view.frustum[3].normal);
5542 // make the corners absolute
5543 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5544 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5545 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5546 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5549 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5551 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5552 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5553 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5554 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5555 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5559 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5560 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5561 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5562 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5563 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5564 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5565 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5566 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5567 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5568 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5570 r_refdef.view.numfrustumplanes = 5;
5572 if (r_refdef.view.useclipplane)
5574 r_refdef.view.numfrustumplanes = 6;
5575 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5578 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5579 PlaneClassify(r_refdef.view.frustum + i);
5581 // LordHavoc: note to all quake engine coders, Quake had a special case
5582 // for 90 degrees which assumed a square view (wrong), so I removed it,
5583 // Quake2 has it disabled as well.
5585 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5586 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5587 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5588 //PlaneClassify(&frustum[0]);
5590 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5591 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5592 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5593 //PlaneClassify(&frustum[1]);
5595 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5596 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5597 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5598 //PlaneClassify(&frustum[2]);
5600 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5601 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5602 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5603 //PlaneClassify(&frustum[3]);
5606 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5607 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5608 //PlaneClassify(&frustum[4]);
5611 static void R_View_UpdateWithScissor(const int *myscissor)
5613 R_Main_ResizeViewCache();
5614 R_View_SetFrustum(myscissor);
5615 R_View_WorldVisibility(r_refdef.view.useclipplane);
5616 R_View_UpdateEntityVisible();
5617 R_View_UpdateEntityLighting();
5620 static void R_View_Update(void)
5622 R_Main_ResizeViewCache();
5623 R_View_SetFrustum(NULL);
5624 R_View_WorldVisibility(r_refdef.view.useclipplane);
5625 R_View_UpdateEntityVisible();
5626 R_View_UpdateEntityLighting();
5629 float viewscalefpsadjusted = 1.0f;
5631 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5633 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5634 scale = bound(0.03125f, scale, 1.0f);
5635 *outwidth = (int)ceil(width * scale);
5636 *outheight = (int)ceil(height * scale);
5639 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5641 const float *customclipplane = NULL;
5643 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5644 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5646 // LordHavoc: couldn't figure out how to make this approach the
5647 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5648 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5649 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5650 dist = r_refdef.view.clipplane.dist;
5651 plane[0] = r_refdef.view.clipplane.normal[0];
5652 plane[1] = r_refdef.view.clipplane.normal[1];
5653 plane[2] = r_refdef.view.clipplane.normal[2];
5655 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5658 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5659 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5661 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5662 if (!r_refdef.view.useperspective)
5663 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);
5664 else if (vid.stencil && r_useinfinitefarclip.integer)
5665 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);
5667 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);
5668 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5669 R_SetViewport(&r_refdef.view.viewport);
5670 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5672 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5673 float screenplane[4];
5674 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5675 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5676 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5677 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5678 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5682 void R_EntityMatrix(const matrix4x4_t *matrix)
5684 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5686 gl_modelmatrixchanged = false;
5687 gl_modelmatrix = *matrix;
5688 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5689 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5690 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5691 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5693 switch(vid.renderpath)
5695 case RENDERPATH_D3D9:
5697 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5698 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5701 case RENDERPATH_D3D10:
5702 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5704 case RENDERPATH_D3D11:
5705 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5707 case RENDERPATH_GL11:
5708 case RENDERPATH_GL13:
5709 case RENDERPATH_GLES1:
5711 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5714 case RENDERPATH_SOFT:
5715 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5716 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5718 case RENDERPATH_GL20:
5719 case RENDERPATH_GLES2:
5720 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5721 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5727 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5729 r_viewport_t viewport;
5733 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5734 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);
5735 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5736 R_SetViewport(&viewport);
5737 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5738 GL_Color(1, 1, 1, 1);
5739 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5740 GL_BlendFunc(GL_ONE, GL_ZERO);
5741 GL_ScissorTest(false);
5742 GL_DepthMask(false);
5743 GL_DepthRange(0, 1);
5744 GL_DepthTest(false);
5745 GL_DepthFunc(GL_LEQUAL);
5746 R_EntityMatrix(&identitymatrix);
5747 R_Mesh_ResetTextureState();
5748 GL_PolygonOffset(0, 0);
5749 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5750 switch(vid.renderpath)
5752 case RENDERPATH_GL11:
5753 case RENDERPATH_GL13:
5754 case RENDERPATH_GL20:
5755 case RENDERPATH_GLES1:
5756 case RENDERPATH_GLES2:
5757 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5759 case RENDERPATH_D3D9:
5760 case RENDERPATH_D3D10:
5761 case RENDERPATH_D3D11:
5762 case RENDERPATH_SOFT:
5765 GL_CullFace(GL_NONE);
5770 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5774 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5777 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5781 R_SetupView(true, fbo, depthtexture, colortexture);
5782 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5783 GL_Color(1, 1, 1, 1);
5784 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5785 GL_BlendFunc(GL_ONE, GL_ZERO);
5786 GL_ScissorTest(true);
5788 GL_DepthRange(0, 1);
5790 GL_DepthFunc(GL_LEQUAL);
5791 R_EntityMatrix(&identitymatrix);
5792 R_Mesh_ResetTextureState();
5793 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5794 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5795 switch(vid.renderpath)
5797 case RENDERPATH_GL11:
5798 case RENDERPATH_GL13:
5799 case RENDERPATH_GL20:
5800 case RENDERPATH_GLES1:
5801 case RENDERPATH_GLES2:
5802 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5804 case RENDERPATH_D3D9:
5805 case RENDERPATH_D3D10:
5806 case RENDERPATH_D3D11:
5807 case RENDERPATH_SOFT:
5810 GL_CullFace(r_refdef.view.cullface_back);
5815 R_RenderView_UpdateViewVectors
5818 void R_RenderView_UpdateViewVectors(void)
5820 // break apart the view matrix into vectors for various purposes
5821 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5822 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5823 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5824 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5825 // make an inverted copy of the view matrix for tracking sprites
5826 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5829 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5830 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5832 static void R_Water_StartFrame(void)
5835 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5836 r_waterstate_waterplane_t *p;
5837 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;
5839 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5842 switch(vid.renderpath)
5844 case RENDERPATH_GL20:
5845 case RENDERPATH_D3D9:
5846 case RENDERPATH_D3D10:
5847 case RENDERPATH_D3D11:
5848 case RENDERPATH_SOFT:
5849 case RENDERPATH_GLES2:
5851 case RENDERPATH_GL11:
5852 case RENDERPATH_GL13:
5853 case RENDERPATH_GLES1:
5857 // set waterwidth and waterheight to the water resolution that will be
5858 // used (often less than the screen resolution for faster rendering)
5859 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5861 // calculate desired texture sizes
5862 // can't use water if the card does not support the texture size
5863 if (!r_water.integer || r_showsurfaces.integer)
5864 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5865 else if (vid.support.arb_texture_non_power_of_two)
5867 texturewidth = waterwidth;
5868 textureheight = waterheight;
5869 camerawidth = waterwidth;
5870 cameraheight = waterheight;
5874 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5875 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5876 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5877 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5880 // allocate textures as needed
5881 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))
5883 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5884 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5886 if (p->texture_refraction)
5887 R_FreeTexture(p->texture_refraction);
5888 p->texture_refraction = NULL;
5889 if (p->fbo_refraction)
5890 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5891 p->fbo_refraction = 0;
5892 if (p->texture_reflection)
5893 R_FreeTexture(p->texture_reflection);
5894 p->texture_reflection = NULL;
5895 if (p->fbo_reflection)
5896 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5897 p->fbo_reflection = 0;
5898 if (p->texture_camera)
5899 R_FreeTexture(p->texture_camera);
5900 p->texture_camera = NULL;
5902 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5905 memset(&r_fb.water, 0, sizeof(r_fb.water));
5906 r_fb.water.texturewidth = texturewidth;
5907 r_fb.water.textureheight = textureheight;
5908 r_fb.water.camerawidth = camerawidth;
5909 r_fb.water.cameraheight = cameraheight;
5912 if (r_fb.water.texturewidth)
5914 int scaledwidth, scaledheight;
5916 r_fb.water.enabled = true;
5918 // water resolution is usually reduced
5919 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5920 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5921 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5923 // set up variables that will be used in shader setup
5924 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5925 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5926 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5927 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5930 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5931 r_fb.water.numwaterplanes = 0;
5934 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5936 int planeindex, bestplaneindex, vertexindex;
5937 vec3_t mins, maxs, normal, center, v, n;
5938 vec_t planescore, bestplanescore;
5940 r_waterstate_waterplane_t *p;
5941 texture_t *t = R_GetCurrentTexture(surface->texture);
5943 rsurface.texture = t;
5944 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5945 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5946 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5948 // average the vertex normals, find the surface bounds (after deformvertexes)
5949 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5950 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5951 VectorCopy(n, normal);
5952 VectorCopy(v, mins);
5953 VectorCopy(v, maxs);
5954 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5956 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5957 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5958 VectorAdd(normal, n, normal);
5959 mins[0] = min(mins[0], v[0]);
5960 mins[1] = min(mins[1], v[1]);
5961 mins[2] = min(mins[2], v[2]);
5962 maxs[0] = max(maxs[0], v[0]);
5963 maxs[1] = max(maxs[1], v[1]);
5964 maxs[2] = max(maxs[2], v[2]);
5966 VectorNormalize(normal);
5967 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5969 VectorCopy(normal, plane.normal);
5970 VectorNormalize(plane.normal);
5971 plane.dist = DotProduct(center, plane.normal);
5972 PlaneClassify(&plane);
5973 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5975 // skip backfaces (except if nocullface is set)
5976 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5978 VectorNegate(plane.normal, plane.normal);
5980 PlaneClassify(&plane);
5984 // find a matching plane if there is one
5985 bestplaneindex = -1;
5986 bestplanescore = 1048576.0f;
5987 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5989 if(p->camera_entity == t->camera_entity)
5991 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5992 if (bestplaneindex < 0 || bestplanescore > planescore)
5994 bestplaneindex = planeindex;
5995 bestplanescore = planescore;
5999 planeindex = bestplaneindex;
6000 p = r_fb.water.waterplanes + planeindex;
6002 // if this surface does not fit any known plane rendered this frame, add one
6003 if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6005 // store the new plane
6006 planeindex = r_fb.water.numwaterplanes++;
6007 p = r_fb.water.waterplanes + planeindex;
6009 // clear materialflags and pvs
6010 p->materialflags = 0;
6011 p->pvsvalid = false;
6012 p->camera_entity = t->camera_entity;
6013 VectorCopy(mins, p->mins);
6014 VectorCopy(maxs, p->maxs);
6018 // merge mins/maxs when we're adding this surface to the plane
6019 p->mins[0] = min(p->mins[0], mins[0]);
6020 p->mins[1] = min(p->mins[1], mins[1]);
6021 p->mins[2] = min(p->mins[2], mins[2]);
6022 p->maxs[0] = max(p->maxs[0], maxs[0]);
6023 p->maxs[1] = max(p->maxs[1], maxs[1]);
6024 p->maxs[2] = max(p->maxs[2], maxs[2]);
6026 // merge this surface's materialflags into the waterplane
6027 p->materialflags |= t->currentmaterialflags;
6028 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6030 // merge this surface's PVS into the waterplane
6031 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6032 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6034 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6040 extern cvar_t r_drawparticles;
6041 extern cvar_t r_drawdecals;
6043 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6046 r_refdef_view_t originalview;
6047 r_refdef_view_t myview;
6048 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;
6049 r_waterstate_waterplane_t *p;
6051 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;
6054 originalview = r_refdef.view;
6056 // lowquality hack, temporarily shut down some cvars and restore afterwards
6057 qualityreduction = r_water_lowquality.integer;
6058 if (qualityreduction > 0)
6060 if (qualityreduction >= 1)
6062 old_r_shadows = r_shadows.integer;
6063 old_r_worldrtlight = r_shadow_realtime_world.integer;
6064 old_r_dlight = r_shadow_realtime_dlight.integer;
6065 Cvar_SetValueQuick(&r_shadows, 0);
6066 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6067 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6069 if (qualityreduction >= 2)
6071 old_r_dynamic = r_dynamic.integer;
6072 old_r_particles = r_drawparticles.integer;
6073 old_r_decals = r_drawdecals.integer;
6074 Cvar_SetValueQuick(&r_dynamic, 0);
6075 Cvar_SetValueQuick(&r_drawparticles, 0);
6076 Cvar_SetValueQuick(&r_drawdecals, 0);
6080 // make sure enough textures are allocated
6081 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6083 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6085 if (!p->texture_refraction)
6086 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);
6087 if (!p->texture_refraction)
6091 if (r_fb.water.depthtexture == NULL)
6092 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6093 if (p->fbo_refraction == 0)
6094 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6097 else if (p->materialflags & MATERIALFLAG_CAMERA)
6099 if (!p->texture_camera)
6100 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);
6101 if (!p->texture_camera)
6105 if (r_fb.water.depthtexture == NULL)
6106 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6107 if (p->fbo_camera == 0)
6108 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6112 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6114 if (!p->texture_reflection)
6115 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);
6116 if (!p->texture_reflection)
6120 if (r_fb.water.depthtexture == NULL)
6121 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6122 if (p->fbo_reflection == 0)
6123 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6129 r_refdef.view = originalview;
6130 r_refdef.view.showdebug = false;
6131 r_refdef.view.width = r_fb.water.waterwidth;
6132 r_refdef.view.height = r_fb.water.waterheight;
6133 r_refdef.view.useclipplane = true;
6134 myview = r_refdef.view;
6135 r_fb.water.renderingscene = true;
6136 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6138 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6140 r_refdef.view = myview;
6141 if(r_water_scissormode.integer)
6143 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6144 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6145 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6148 // render reflected scene and copy into texture
6149 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6150 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6151 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6152 r_refdef.view.clipplane = p->plane;
6153 // reverse the cullface settings for this render
6154 r_refdef.view.cullface_front = GL_FRONT;
6155 r_refdef.view.cullface_back = GL_BACK;
6156 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6158 r_refdef.view.usecustompvs = true;
6160 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6162 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6165 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6166 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6167 R_ClearScreen(r_refdef.fogenabled);
6168 if(r_water_scissormode.integer & 2)
6169 R_View_UpdateWithScissor(myscissor);
6172 R_AnimCache_CacheVisibleEntities();
6173 if(r_water_scissormode.integer & 1)
6174 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6175 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6177 if (!p->fbo_reflection)
6178 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);
6179 r_fb.water.hideplayer = false;
6182 // render the normal view scene and copy into texture
6183 // (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)
6184 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6186 r_refdef.view = myview;
6187 if(r_water_scissormode.integer)
6189 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6190 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6191 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6194 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6196 r_refdef.view.clipplane = p->plane;
6197 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6198 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6200 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6202 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6203 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6204 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6205 R_RenderView_UpdateViewVectors();
6206 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6208 r_refdef.view.usecustompvs = true;
6209 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);
6213 PlaneClassify(&r_refdef.view.clipplane);
6215 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6216 R_ClearScreen(r_refdef.fogenabled);
6217 if(r_water_scissormode.integer & 2)
6218 R_View_UpdateWithScissor(myscissor);
6221 R_AnimCache_CacheVisibleEntities();
6222 if(r_water_scissormode.integer & 1)
6223 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6224 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6226 if (!p->fbo_refraction)
6227 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);
6228 r_fb.water.hideplayer = false;
6230 else if (p->materialflags & MATERIALFLAG_CAMERA)
6232 r_refdef.view = myview;
6234 r_refdef.view.clipplane = p->plane;
6235 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6236 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6238 r_refdef.view.width = r_fb.water.camerawidth;
6239 r_refdef.view.height = r_fb.water.cameraheight;
6240 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6241 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6242 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6243 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6245 if(p->camera_entity)
6247 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6248 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6251 // note: all of the view is used for displaying... so
6252 // there is no use in scissoring
6254 // reverse the cullface settings for this render
6255 r_refdef.view.cullface_front = GL_FRONT;
6256 r_refdef.view.cullface_back = GL_BACK;
6257 // also reverse the view matrix
6258 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
6259 R_RenderView_UpdateViewVectors();
6260 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6262 r_refdef.view.usecustompvs = true;
6263 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);
6266 // camera needs no clipplane
6267 r_refdef.view.useclipplane = false;
6269 PlaneClassify(&r_refdef.view.clipplane);
6271 r_fb.water.hideplayer = false;
6273 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6274 R_ClearScreen(r_refdef.fogenabled);
6276 R_AnimCache_CacheVisibleEntities();
6277 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6280 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);
6281 r_fb.water.hideplayer = false;
6285 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6286 r_fb.water.renderingscene = false;
6287 r_refdef.view = originalview;
6288 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6289 if (!r_fb.water.depthtexture)
6290 R_ClearScreen(r_refdef.fogenabled);
6292 R_AnimCache_CacheVisibleEntities();
6295 r_refdef.view = originalview;
6296 r_fb.water.renderingscene = false;
6297 Cvar_SetValueQuick(&r_water, 0);
6298 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6300 // lowquality hack, restore cvars
6301 if (qualityreduction > 0)
6303 if (qualityreduction >= 1)
6305 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6306 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6307 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6309 if (qualityreduction >= 2)
6311 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6312 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6313 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6318 static void R_Bloom_StartFrame(void)
6321 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6322 int viewwidth, viewheight;
6323 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6324 textype_t textype = TEXTYPE_COLORBUFFER;
6326 switch (vid.renderpath)
6328 case RENDERPATH_GL20:
6329 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6330 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6332 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6333 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6336 case RENDERPATH_GL11:
6337 case RENDERPATH_GL13:
6338 case RENDERPATH_GLES1:
6339 case RENDERPATH_GLES2:
6340 case RENDERPATH_D3D9:
6341 case RENDERPATH_D3D10:
6342 case RENDERPATH_D3D11:
6343 r_fb.usedepthtextures = false;
6345 case RENDERPATH_SOFT:
6346 r_fb.usedepthtextures = true;
6350 if (r_viewscale_fpsscaling.integer)
6352 double actualframetime;
6353 double targetframetime;
6355 actualframetime = r_refdef.lastdrawscreentime;
6356 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6357 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6358 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6359 if (r_viewscale_fpsscaling_stepsize.value > 0)
6360 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6361 viewscalefpsadjusted += adjust;
6362 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6365 viewscalefpsadjusted = 1.0f;
6367 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6369 switch(vid.renderpath)
6371 case RENDERPATH_GL20:
6372 case RENDERPATH_D3D9:
6373 case RENDERPATH_D3D10:
6374 case RENDERPATH_D3D11:
6375 case RENDERPATH_SOFT:
6376 case RENDERPATH_GLES2:
6378 case RENDERPATH_GL11:
6379 case RENDERPATH_GL13:
6380 case RENDERPATH_GLES1:
6384 // set bloomwidth and bloomheight to the bloom resolution that will be
6385 // used (often less than the screen resolution for faster rendering)
6386 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6387 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6388 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6389 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6390 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6392 // calculate desired texture sizes
6393 if (vid.support.arb_texture_non_power_of_two)
6395 screentexturewidth = vid.width;
6396 screentextureheight = vid.height;
6397 bloomtexturewidth = r_fb.bloomwidth;
6398 bloomtextureheight = r_fb.bloomheight;
6402 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6403 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6404 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6405 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6408 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))
6410 Cvar_SetValueQuick(&r_bloom, 0);
6411 Cvar_SetValueQuick(&r_motionblur, 0);
6412 Cvar_SetValueQuick(&r_damageblur, 0);
6415 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6417 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6419 && r_viewscale.value == 1.0f
6420 && !r_viewscale_fpsscaling.integer)
6421 screentexturewidth = screentextureheight = 0;
6422 if (!r_bloom.integer)
6423 bloomtexturewidth = bloomtextureheight = 0;
6425 // allocate textures as needed
6426 if (r_fb.screentexturewidth != screentexturewidth
6427 || r_fb.screentextureheight != screentextureheight
6428 || r_fb.bloomtexturewidth != bloomtexturewidth
6429 || r_fb.bloomtextureheight != bloomtextureheight
6430 || r_fb.textype != textype
6431 || useviewfbo != (r_fb.fbo != 0))
6433 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6435 if (r_fb.bloomtexture[i])
6436 R_FreeTexture(r_fb.bloomtexture[i]);
6437 r_fb.bloomtexture[i] = NULL;
6439 if (r_fb.bloomfbo[i])
6440 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6441 r_fb.bloomfbo[i] = 0;
6445 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6448 if (r_fb.colortexture)
6449 R_FreeTexture(r_fb.colortexture);
6450 r_fb.colortexture = NULL;
6452 if (r_fb.depthtexture)
6453 R_FreeTexture(r_fb.depthtexture);
6454 r_fb.depthtexture = NULL;
6456 if (r_fb.ghosttexture)
6457 R_FreeTexture(r_fb.ghosttexture);
6458 r_fb.ghosttexture = NULL;
6460 r_fb.screentexturewidth = screentexturewidth;
6461 r_fb.screentextureheight = screentextureheight;
6462 r_fb.bloomtexturewidth = bloomtexturewidth;
6463 r_fb.bloomtextureheight = bloomtextureheight;
6464 r_fb.textype = textype;
6466 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6468 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6469 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);
6470 r_fb.ghosttexture_valid = false;
6471 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);
6474 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6475 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6476 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6480 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6482 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6484 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);
6486 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6491 // bloom texture is a different resolution
6492 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6493 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6494 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6495 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6496 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6498 // set up a texcoord array for the full resolution screen image
6499 // (we have to keep this around to copy back during final render)
6500 r_fb.screentexcoord2f[0] = 0;
6501 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6502 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6503 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6504 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6505 r_fb.screentexcoord2f[5] = 0;
6506 r_fb.screentexcoord2f[6] = 0;
6507 r_fb.screentexcoord2f[7] = 0;
6511 for (i = 1;i < 8;i += 2)
6513 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6517 // set up a texcoord array for the reduced resolution bloom image
6518 // (which will be additive blended over the screen image)
6519 r_fb.bloomtexcoord2f[0] = 0;
6520 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6521 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6522 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6523 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6524 r_fb.bloomtexcoord2f[5] = 0;
6525 r_fb.bloomtexcoord2f[6] = 0;
6526 r_fb.bloomtexcoord2f[7] = 0;
6528 switch(vid.renderpath)
6530 case RENDERPATH_GL11:
6531 case RENDERPATH_GL13:
6532 case RENDERPATH_GL20:
6533 case RENDERPATH_SOFT:
6534 case RENDERPATH_GLES1:
6535 case RENDERPATH_GLES2:
6537 case RENDERPATH_D3D9:
6538 case RENDERPATH_D3D10:
6539 case RENDERPATH_D3D11:
6540 for (i = 0;i < 4;i++)
6542 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6543 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6544 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6545 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6550 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6553 r_refdef.view.clear = true;
6556 static void R_Bloom_MakeTexture(void)
6559 float xoffset, yoffset, r, brighten;
6561 float colorscale = r_bloom_colorscale.value;
6563 r_refdef.stats[r_stat_bloom]++;
6566 // this copy is unnecessary since it happens in R_BlendView already
6569 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);
6570 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6574 // scale down screen texture to the bloom texture size
6576 r_fb.bloomindex = 0;
6577 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6578 R_SetViewport(&r_fb.bloomviewport);
6579 GL_DepthTest(false);
6580 GL_BlendFunc(GL_ONE, GL_ZERO);
6581 GL_Color(colorscale, colorscale, colorscale, 1);
6582 // 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...
6583 switch(vid.renderpath)
6585 case RENDERPATH_GL11:
6586 case RENDERPATH_GL13:
6587 case RENDERPATH_GL20:
6588 case RENDERPATH_GLES1:
6589 case RENDERPATH_GLES2:
6590 case RENDERPATH_SOFT:
6591 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6593 case RENDERPATH_D3D9:
6594 case RENDERPATH_D3D10:
6595 case RENDERPATH_D3D11:
6596 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6599 // TODO: do boxfilter scale-down in shader?
6600 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6601 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6602 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6604 // we now have a properly scaled bloom image
6605 if (!r_fb.bloomfbo[r_fb.bloomindex])
6607 // copy it into the bloom texture
6608 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);
6609 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6612 // multiply bloom image by itself as many times as desired
6613 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6615 intex = r_fb.bloomtexture[r_fb.bloomindex];
6616 r_fb.bloomindex ^= 1;
6617 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6619 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6620 if (!r_fb.bloomfbo[r_fb.bloomindex])
6622 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6623 GL_Color(r,r,r,1); // apply fix factor
6628 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6629 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6630 GL_Color(1,1,1,1); // no fix factor supported here
6632 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6633 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6634 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6635 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6637 if (!r_fb.bloomfbo[r_fb.bloomindex])
6639 // copy the darkened image to a texture
6640 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);
6641 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6645 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6646 brighten = r_bloom_brighten.value;
6647 brighten = sqrt(brighten);
6649 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6651 for (dir = 0;dir < 2;dir++)
6653 intex = r_fb.bloomtexture[r_fb.bloomindex];
6654 r_fb.bloomindex ^= 1;
6655 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6656 // blend on at multiple vertical offsets to achieve a vertical blur
6657 // TODO: do offset blends using GLSL
6658 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6659 GL_BlendFunc(GL_ONE, GL_ZERO);
6660 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6661 for (x = -range;x <= range;x++)
6663 if (!dir){xoffset = 0;yoffset = x;}
6664 else {xoffset = x;yoffset = 0;}
6665 xoffset /= (float)r_fb.bloomtexturewidth;
6666 yoffset /= (float)r_fb.bloomtextureheight;
6667 // compute a texcoord array with the specified x and y offset
6668 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6669 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6670 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6671 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6672 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6673 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6674 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6675 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6676 // this r value looks like a 'dot' particle, fading sharply to
6677 // black at the edges
6678 // (probably not realistic but looks good enough)
6679 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6680 //r = brighten/(range*2+1);
6681 r = brighten / (range * 2 + 1);
6683 r *= (1 - x*x/(float)(range*range));
6684 GL_Color(r, r, r, 1);
6685 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6686 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6687 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6688 GL_BlendFunc(GL_ONE, GL_ONE);
6691 if (!r_fb.bloomfbo[r_fb.bloomindex])
6693 // copy the vertically or horizontally blurred bloom view to a texture
6694 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);
6695 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6700 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6702 unsigned int permutation;
6703 float uservecs[4][4];
6705 R_EntityMatrix(&identitymatrix);
6707 switch (vid.renderpath)
6709 case RENDERPATH_GL20:
6710 case RENDERPATH_D3D9:
6711 case RENDERPATH_D3D10:
6712 case RENDERPATH_D3D11:
6713 case RENDERPATH_SOFT:
6714 case RENDERPATH_GLES2:
6716 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6717 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6718 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6719 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6720 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6722 if (r_fb.colortexture)
6726 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);
6727 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6730 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6732 // declare variables
6733 float blur_factor, blur_mouseaccel, blur_velocity;
6734 static float blur_average;
6735 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6737 // set a goal for the factoring
6738 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6739 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6740 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6741 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6742 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6743 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6745 // from the goal, pick an averaged value between goal and last value
6746 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6747 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6749 // enforce minimum amount of blur
6750 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6752 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6754 // calculate values into a standard alpha
6755 cl.motionbluralpha = 1 - exp(-
6757 (r_motionblur.value * blur_factor / 80)
6759 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6762 max(0.0001, cl.time - cl.oldtime) // fps independent
6765 // randomization for the blur value to combat persistent ghosting
6766 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6767 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6770 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6771 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6773 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6774 GL_Color(1, 1, 1, cl.motionbluralpha);
6775 switch(vid.renderpath)
6777 case RENDERPATH_GL11:
6778 case RENDERPATH_GL13:
6779 case RENDERPATH_GL20:
6780 case RENDERPATH_GLES1:
6781 case RENDERPATH_GLES2:
6782 case RENDERPATH_SOFT:
6783 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6785 case RENDERPATH_D3D9:
6786 case RENDERPATH_D3D10:
6787 case RENDERPATH_D3D11:
6788 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6791 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6792 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6793 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6796 // updates old view angles for next pass
6797 VectorCopy(cl.viewangles, blur_oldangles);
6799 // copy view into the ghost texture
6800 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);
6801 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6802 r_fb.ghosttexture_valid = true;
6807 // no r_fb.colortexture means we're rendering to the real fb
6808 // we may still have to do view tint...
6809 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6811 // apply a color tint to the whole view
6812 R_ResetViewRendering2D(0, NULL, NULL);
6813 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6814 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6815 R_SetupShader_Generic_NoTexture(false, true);
6816 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6817 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6819 break; // no screen processing, no bloom, skip it
6822 if (r_fb.bloomtexture[0])
6824 // make the bloom texture
6825 R_Bloom_MakeTexture();
6828 #if _MSC_VER >= 1400
6829 #define sscanf sscanf_s
6831 memset(uservecs, 0, sizeof(uservecs));
6832 if (r_glsl_postprocess_uservec1_enable.integer)
6833 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6834 if (r_glsl_postprocess_uservec2_enable.integer)
6835 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6836 if (r_glsl_postprocess_uservec3_enable.integer)
6837 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6838 if (r_glsl_postprocess_uservec4_enable.integer)
6839 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6841 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6842 GL_Color(1, 1, 1, 1);
6843 GL_BlendFunc(GL_ONE, GL_ZERO);
6845 switch(vid.renderpath)
6847 case RENDERPATH_GL20:
6848 case RENDERPATH_GLES2:
6849 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6850 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6851 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6852 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6853 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6854 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]);
6855 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6856 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]);
6857 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]);
6858 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]);
6859 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]);
6860 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6861 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6862 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);
6864 case RENDERPATH_D3D9:
6866 // 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...
6867 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6868 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6869 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6870 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6871 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6872 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6873 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6874 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6875 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6876 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6877 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6878 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6879 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6880 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6883 case RENDERPATH_D3D10:
6884 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6886 case RENDERPATH_D3D11:
6887 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6889 case RENDERPATH_SOFT:
6890 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6891 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6892 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6893 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6894 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6895 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6896 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6897 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6898 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6899 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6900 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6901 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6902 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6903 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6908 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6909 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6911 case RENDERPATH_GL11:
6912 case RENDERPATH_GL13:
6913 case RENDERPATH_GLES1:
6914 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6916 // apply a color tint to the whole view
6917 R_ResetViewRendering2D(0, NULL, NULL);
6918 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6919 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6920 R_SetupShader_Generic_NoTexture(false, true);
6921 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6922 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6928 matrix4x4_t r_waterscrollmatrix;
6930 void R_UpdateFog(void)
6933 if (gamemode == GAME_NEHAHRA)
6935 if (gl_fogenable.integer)
6937 r_refdef.oldgl_fogenable = true;
6938 r_refdef.fog_density = gl_fogdensity.value;
6939 r_refdef.fog_red = gl_fogred.value;
6940 r_refdef.fog_green = gl_foggreen.value;
6941 r_refdef.fog_blue = gl_fogblue.value;
6942 r_refdef.fog_alpha = 1;
6943 r_refdef.fog_start = 0;
6944 r_refdef.fog_end = gl_skyclip.value;
6945 r_refdef.fog_height = 1<<30;
6946 r_refdef.fog_fadedepth = 128;
6948 else if (r_refdef.oldgl_fogenable)
6950 r_refdef.oldgl_fogenable = false;
6951 r_refdef.fog_density = 0;
6952 r_refdef.fog_red = 0;
6953 r_refdef.fog_green = 0;
6954 r_refdef.fog_blue = 0;
6955 r_refdef.fog_alpha = 0;
6956 r_refdef.fog_start = 0;
6957 r_refdef.fog_end = 0;
6958 r_refdef.fog_height = 1<<30;
6959 r_refdef.fog_fadedepth = 128;
6964 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6965 r_refdef.fog_start = max(0, r_refdef.fog_start);
6966 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6968 if (r_refdef.fog_density && r_drawfog.integer)
6970 r_refdef.fogenabled = true;
6971 // this is the point where the fog reaches 0.9986 alpha, which we
6972 // consider a good enough cutoff point for the texture
6973 // (0.9986 * 256 == 255.6)
6974 if (r_fog_exp2.integer)
6975 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6977 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6978 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6979 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6980 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6981 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6982 R_BuildFogHeightTexture();
6983 // fog color was already set
6984 // update the fog texture
6985 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)
6986 R_BuildFogTexture();
6987 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6988 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6991 r_refdef.fogenabled = false;
6994 if (r_refdef.fog_density)
6996 r_refdef.fogcolor[0] = r_refdef.fog_red;
6997 r_refdef.fogcolor[1] = r_refdef.fog_green;
6998 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7000 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7001 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7002 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7003 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7007 VectorCopy(r_refdef.fogcolor, fogvec);
7008 // color.rgb *= ContrastBoost * SceneBrightness;
7009 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7010 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7011 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7012 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7017 void R_UpdateVariables(void)
7021 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7023 r_refdef.farclip = r_farclip_base.value;
7024 if (r_refdef.scene.worldmodel)
7025 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7026 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7028 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7029 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7030 r_refdef.polygonfactor = 0;
7031 r_refdef.polygonoffset = 0;
7032 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7033 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7035 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7036 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7037 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7038 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7039 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7040 if (FAKELIGHT_ENABLED)
7042 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7044 else if (r_refdef.scene.worldmodel)
7046 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7048 if (r_showsurfaces.integer)
7050 r_refdef.scene.rtworld = false;
7051 r_refdef.scene.rtworldshadows = false;
7052 r_refdef.scene.rtdlight = false;
7053 r_refdef.scene.rtdlightshadows = false;
7054 r_refdef.lightmapintensity = 0;
7057 r_gpuskeletal = false;
7058 switch(vid.renderpath)
7060 case RENDERPATH_GL20:
7061 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7062 case RENDERPATH_D3D9:
7063 case RENDERPATH_D3D10:
7064 case RENDERPATH_D3D11:
7065 case RENDERPATH_SOFT:
7066 case RENDERPATH_GLES2:
7067 if(v_glslgamma.integer && !vid_gammatables_trivial)
7069 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7071 // build GLSL gamma texture
7072 #define RAMPWIDTH 256
7073 unsigned short ramp[RAMPWIDTH * 3];
7074 unsigned char rampbgr[RAMPWIDTH][4];
7077 r_texture_gammaramps_serial = vid_gammatables_serial;
7079 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7080 for(i = 0; i < RAMPWIDTH; ++i)
7082 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7083 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7084 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7087 if (r_texture_gammaramps)
7089 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7093 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7099 // remove GLSL gamma texture
7102 case RENDERPATH_GL11:
7103 case RENDERPATH_GL13:
7104 case RENDERPATH_GLES1:
7109 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7110 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7116 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7117 if( scenetype != r_currentscenetype ) {
7118 // store the old scenetype
7119 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7120 r_currentscenetype = scenetype;
7121 // move in the new scene
7122 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7131 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7133 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7134 if( scenetype == r_currentscenetype ) {
7135 return &r_refdef.scene;
7137 return &r_scenes_store[ scenetype ];
7141 static int R_SortEntities_Compare(const void *ap, const void *bp)
7143 const entity_render_t *a = *(const entity_render_t **)ap;
7144 const entity_render_t *b = *(const entity_render_t **)bp;
7147 if(a->model < b->model)
7149 if(a->model > b->model)
7153 // TODO possibly calculate the REAL skinnum here first using
7155 if(a->skinnum < b->skinnum)
7157 if(a->skinnum > b->skinnum)
7160 // everything we compared is equal
7163 static void R_SortEntities(void)
7165 // below or equal 2 ents, sorting never gains anything
7166 if(r_refdef.scene.numentities <= 2)
7169 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7177 int dpsoftrast_test;
7178 extern cvar_t r_shadow_bouncegrid;
7179 void R_RenderView(void)
7181 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7183 rtexture_t *depthtexture;
7184 rtexture_t *colortexture;
7186 dpsoftrast_test = r_test.integer;
7188 if (r_timereport_active)
7189 R_TimeReport("start");
7190 r_textureframe++; // used only by R_GetCurrentTexture
7191 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7193 if(R_CompileShader_CheckStaticParms())
7196 if (!r_drawentities.integer)
7197 r_refdef.scene.numentities = 0;
7198 else if (r_sortentities.integer)
7201 R_AnimCache_ClearCache();
7203 /* adjust for stereo display */
7204 if(R_Stereo_Active())
7206 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);
7207 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7210 if (r_refdef.view.isoverlay)
7212 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7213 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7214 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7215 R_TimeReport("depthclear");
7217 r_refdef.view.showdebug = false;
7219 r_fb.water.enabled = false;
7220 r_fb.water.numwaterplanes = 0;
7222 R_RenderScene(0, NULL, NULL);
7224 r_refdef.view.matrix = originalmatrix;
7230 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7232 r_refdef.view.matrix = originalmatrix;
7236 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7238 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7239 // in sRGB fallback, behave similar to true sRGB: convert this
7240 // value from linear to sRGB
7241 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7243 R_RenderView_UpdateViewVectors();
7245 R_Shadow_UpdateWorldLightSelection();
7247 R_Bloom_StartFrame();
7249 // apply bloom brightness offset
7250 if(r_fb.bloomtexture[0])
7251 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7253 R_Water_StartFrame();
7255 // now we probably have an fbo to render into
7257 depthtexture = r_fb.depthtexture;
7258 colortexture = r_fb.colortexture;
7261 if (r_timereport_active)
7262 R_TimeReport("viewsetup");
7264 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7266 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7268 R_ClearScreen(r_refdef.fogenabled);
7269 if (r_timereport_active)
7270 R_TimeReport("viewclear");
7272 r_refdef.view.clear = true;
7274 r_refdef.view.showdebug = true;
7277 if (r_timereport_active)
7278 R_TimeReport("visibility");
7280 R_AnimCache_CacheVisibleEntities();
7281 if (r_timereport_active)
7282 R_TimeReport("animcache");
7284 R_Shadow_UpdateBounceGridTexture();
7285 if (r_timereport_active && r_shadow_bouncegrid.integer)
7286 R_TimeReport("bouncegrid");
7288 r_fb.water.numwaterplanes = 0;
7289 if (r_fb.water.enabled)
7290 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7292 R_RenderScene(fbo, depthtexture, colortexture);
7293 r_fb.water.numwaterplanes = 0;
7295 R_BlendView(fbo, depthtexture, colortexture);
7296 if (r_timereport_active)
7297 R_TimeReport("blendview");
7299 GL_Scissor(0, 0, vid.width, vid.height);
7300 GL_ScissorTest(false);
7302 r_refdef.view.matrix = originalmatrix;
7307 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7309 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7311 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7312 if (r_timereport_active)
7313 R_TimeReport("waterworld");
7316 // don't let sound skip if going slow
7317 if (r_refdef.scene.extraupdate)
7320 R_DrawModelsAddWaterPlanes();
7321 if (r_timereport_active)
7322 R_TimeReport("watermodels");
7324 if (r_fb.water.numwaterplanes)
7326 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7327 if (r_timereport_active)
7328 R_TimeReport("waterscenes");
7332 extern cvar_t cl_locs_show;
7333 static void R_DrawLocs(void);
7334 static void R_DrawEntityBBoxes(void);
7335 static void R_DrawModelDecals(void);
7336 extern cvar_t cl_decals_newsystem;
7337 extern qboolean r_shadow_usingdeferredprepass;
7338 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7340 qboolean shadowmapping = false;
7342 if (r_timereport_active)
7343 R_TimeReport("beginscene");
7345 r_refdef.stats[r_stat_renders]++;
7349 // don't let sound skip if going slow
7350 if (r_refdef.scene.extraupdate)
7353 R_MeshQueue_BeginScene();
7357 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);
7359 if (r_timereport_active)
7360 R_TimeReport("skystartframe");
7362 if (cl.csqc_vidvars.drawworld)
7364 // don't let sound skip if going slow
7365 if (r_refdef.scene.extraupdate)
7368 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7370 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7371 if (r_timereport_active)
7372 R_TimeReport("worldsky");
7375 if (R_DrawBrushModelsSky() && r_timereport_active)
7376 R_TimeReport("bmodelsky");
7378 if (skyrendermasked && skyrenderlater)
7380 // we have to force off the water clipping plane while rendering sky
7381 R_SetupView(false, fbo, depthtexture, colortexture);
7383 R_SetupView(true, fbo, depthtexture, colortexture);
7384 if (r_timereport_active)
7385 R_TimeReport("sky");
7389 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7390 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7391 R_Shadow_PrepareModelShadows();
7392 if (r_timereport_active)
7393 R_TimeReport("preparelights");
7395 if (R_Shadow_ShadowMappingEnabled())
7396 shadowmapping = true;
7398 if (r_shadow_usingdeferredprepass)
7399 R_Shadow_DrawPrepass();
7401 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7403 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7404 if (r_timereport_active)
7405 R_TimeReport("worlddepth");
7407 if (r_depthfirst.integer >= 2)
7409 R_DrawModelsDepth();
7410 if (r_timereport_active)
7411 R_TimeReport("modeldepth");
7414 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7416 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7417 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7418 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7419 // don't let sound skip if going slow
7420 if (r_refdef.scene.extraupdate)
7424 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7426 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7427 if (r_timereport_active)
7428 R_TimeReport("world");
7431 // don't let sound skip if going slow
7432 if (r_refdef.scene.extraupdate)
7436 if (r_timereport_active)
7437 R_TimeReport("models");
7439 // don't let sound skip if going slow
7440 if (r_refdef.scene.extraupdate)
7443 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7445 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7446 R_DrawModelShadows(fbo, depthtexture, colortexture);
7447 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7448 // don't let sound skip if going slow
7449 if (r_refdef.scene.extraupdate)
7453 if (!r_shadow_usingdeferredprepass)
7455 R_Shadow_DrawLights();
7456 if (r_timereport_active)
7457 R_TimeReport("rtlights");
7460 // don't let sound skip if going slow
7461 if (r_refdef.scene.extraupdate)
7464 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7466 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7467 R_DrawModelShadows(fbo, depthtexture, colortexture);
7468 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7469 // don't let sound skip if going slow
7470 if (r_refdef.scene.extraupdate)
7474 if (cl.csqc_vidvars.drawworld)
7476 if (cl_decals_newsystem.integer)
7478 R_DrawModelDecals();
7479 if (r_timereport_active)
7480 R_TimeReport("modeldecals");
7485 if (r_timereport_active)
7486 R_TimeReport("decals");
7490 if (r_timereport_active)
7491 R_TimeReport("particles");
7494 if (r_timereport_active)
7495 R_TimeReport("explosions");
7497 R_DrawLightningBeams();
7498 if (r_timereport_active)
7499 R_TimeReport("lightning");
7503 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7505 if (r_refdef.view.showdebug)
7507 if (cl_locs_show.integer)
7510 if (r_timereport_active)
7511 R_TimeReport("showlocs");
7514 if (r_drawportals.integer)
7517 if (r_timereport_active)
7518 R_TimeReport("portals");
7521 if (r_showbboxes.value > 0)
7523 R_DrawEntityBBoxes();
7524 if (r_timereport_active)
7525 R_TimeReport("bboxes");
7529 if (r_transparent.integer)
7531 R_MeshQueue_RenderTransparent();
7532 if (r_timereport_active)
7533 R_TimeReport("drawtrans");
7536 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))
7538 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7539 if (r_timereport_active)
7540 R_TimeReport("worlddebug");
7541 R_DrawModelsDebug();
7542 if (r_timereport_active)
7543 R_TimeReport("modeldebug");
7546 if (cl.csqc_vidvars.drawworld)
7548 R_Shadow_DrawCoronas();
7549 if (r_timereport_active)
7550 R_TimeReport("coronas");
7555 GL_DepthTest(false);
7556 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7557 GL_Color(1, 1, 1, 1);
7558 qglBegin(GL_POLYGON);
7559 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7560 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7561 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7562 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7564 qglBegin(GL_POLYGON);
7565 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]);
7566 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]);
7567 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]);
7568 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]);
7570 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7574 // don't let sound skip if going slow
7575 if (r_refdef.scene.extraupdate)
7579 static const unsigned short bboxelements[36] =
7589 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7592 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7594 RSurf_ActiveWorldEntity();
7596 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7597 GL_DepthMask(false);
7598 GL_DepthRange(0, 1);
7599 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7600 // R_Mesh_ResetTextureState();
7602 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7603 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7604 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7605 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7606 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7607 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7608 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7609 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7610 R_FillColors(color4f, 8, cr, cg, cb, ca);
7611 if (r_refdef.fogenabled)
7613 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7615 f1 = RSurf_FogVertex(v);
7617 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7618 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7619 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7622 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7623 R_Mesh_ResetTextureState();
7624 R_SetupShader_Generic_NoTexture(false, false);
7625 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7628 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7630 prvm_prog_t *prog = SVVM_prog;
7633 prvm_edict_t *edict;
7635 // this function draws bounding boxes of server entities
7639 GL_CullFace(GL_NONE);
7640 R_SetupShader_Generic_NoTexture(false, false);
7642 for (i = 0;i < numsurfaces;i++)
7644 edict = PRVM_EDICT_NUM(surfacelist[i]);
7645 switch ((int)PRVM_serveredictfloat(edict, solid))
7647 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7648 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7649 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7650 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7651 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7652 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7653 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7655 color[3] *= r_showbboxes.value;
7656 color[3] = bound(0, color[3], 1);
7657 GL_DepthTest(!r_showdisabledepthtest.integer);
7658 GL_CullFace(r_refdef.view.cullface_front);
7659 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7663 static void R_DrawEntityBBoxes(void)
7666 prvm_edict_t *edict;
7668 prvm_prog_t *prog = SVVM_prog;
7670 // this function draws bounding boxes of server entities
7674 for (i = 0;i < prog->num_edicts;i++)
7676 edict = PRVM_EDICT_NUM(i);
7677 if (edict->priv.server->free)
7679 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7680 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7682 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7684 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7685 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7689 static const int nomodelelement3i[24] =
7701 static const unsigned short nomodelelement3s[24] =
7713 static const float nomodelvertex3f[6*3] =
7723 static const float nomodelcolor4f[6*4] =
7725 0.0f, 0.0f, 0.5f, 1.0f,
7726 0.0f, 0.0f, 0.5f, 1.0f,
7727 0.0f, 0.5f, 0.0f, 1.0f,
7728 0.0f, 0.5f, 0.0f, 1.0f,
7729 0.5f, 0.0f, 0.0f, 1.0f,
7730 0.5f, 0.0f, 0.0f, 1.0f
7733 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7739 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);
7741 // this is only called once per entity so numsurfaces is always 1, and
7742 // surfacelist is always {0}, so this code does not handle batches
7744 if (rsurface.ent_flags & RENDER_ADDITIVE)
7746 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7747 GL_DepthMask(false);
7749 else if (rsurface.colormod[3] < 1)
7751 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7752 GL_DepthMask(false);
7756 GL_BlendFunc(GL_ONE, GL_ZERO);
7759 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7760 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7761 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7762 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7763 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7764 for (i = 0, c = color4f;i < 6;i++, c += 4)
7766 c[0] *= rsurface.colormod[0];
7767 c[1] *= rsurface.colormod[1];
7768 c[2] *= rsurface.colormod[2];
7769 c[3] *= rsurface.colormod[3];
7771 if (r_refdef.fogenabled)
7773 for (i = 0, c = color4f;i < 6;i++, c += 4)
7775 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7777 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7778 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7779 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7782 // R_Mesh_ResetTextureState();
7783 R_SetupShader_Generic_NoTexture(false, false);
7784 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7785 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7788 void R_DrawNoModel(entity_render_t *ent)
7791 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7792 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7793 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7795 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7798 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7800 vec3_t right1, right2, diff, normal;
7802 VectorSubtract (org2, org1, normal);
7804 // calculate 'right' vector for start
7805 VectorSubtract (r_refdef.view.origin, org1, diff);
7806 CrossProduct (normal, diff, right1);
7807 VectorNormalize (right1);
7809 // calculate 'right' vector for end
7810 VectorSubtract (r_refdef.view.origin, org2, diff);
7811 CrossProduct (normal, diff, right2);
7812 VectorNormalize (right2);
7814 vert[ 0] = org1[0] + width * right1[0];
7815 vert[ 1] = org1[1] + width * right1[1];
7816 vert[ 2] = org1[2] + width * right1[2];
7817 vert[ 3] = org1[0] - width * right1[0];
7818 vert[ 4] = org1[1] - width * right1[1];
7819 vert[ 5] = org1[2] - width * right1[2];
7820 vert[ 6] = org2[0] - width * right2[0];
7821 vert[ 7] = org2[1] - width * right2[1];
7822 vert[ 8] = org2[2] - width * right2[2];
7823 vert[ 9] = org2[0] + width * right2[0];
7824 vert[10] = org2[1] + width * right2[1];
7825 vert[11] = org2[2] + width * right2[2];
7828 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)
7830 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7831 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7832 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7833 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7834 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7835 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7836 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7837 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7838 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7839 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7840 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7841 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7844 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7849 VectorSet(v, x, y, z);
7850 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7851 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7853 if (i == mesh->numvertices)
7855 if (mesh->numvertices < mesh->maxvertices)
7857 VectorCopy(v, vertex3f);
7858 mesh->numvertices++;
7860 return mesh->numvertices;
7866 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7870 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7871 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7872 e = mesh->element3i + mesh->numtriangles * 3;
7873 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7875 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7876 if (mesh->numtriangles < mesh->maxtriangles)
7881 mesh->numtriangles++;
7883 element[1] = element[2];
7887 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7891 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7892 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7893 e = mesh->element3i + mesh->numtriangles * 3;
7894 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7896 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7897 if (mesh->numtriangles < mesh->maxtriangles)
7902 mesh->numtriangles++;
7904 element[1] = element[2];
7908 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7909 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7911 int planenum, planenum2;
7914 mplane_t *plane, *plane2;
7916 double temppoints[2][256*3];
7917 // figure out how large a bounding box we need to properly compute this brush
7919 for (w = 0;w < numplanes;w++)
7920 maxdist = max(maxdist, fabs(planes[w].dist));
7921 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7922 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7923 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7927 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7928 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7930 if (planenum2 == planenum)
7932 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);
7935 if (tempnumpoints < 3)
7937 // generate elements forming a triangle fan for this polygon
7938 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7942 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)
7944 texturelayer_t *layer;
7945 layer = t->currentlayers + t->currentnumlayers++;
7947 layer->depthmask = depthmask;
7948 layer->blendfunc1 = blendfunc1;
7949 layer->blendfunc2 = blendfunc2;
7950 layer->texture = texture;
7951 layer->texmatrix = *matrix;
7952 layer->color[0] = r;
7953 layer->color[1] = g;
7954 layer->color[2] = b;
7955 layer->color[3] = a;
7958 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7960 if(parms[0] == 0 && parms[1] == 0)
7962 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7963 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7968 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7971 index = parms[2] + rsurface.shadertime * parms[3];
7972 index -= floor(index);
7973 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7976 case Q3WAVEFUNC_NONE:
7977 case Q3WAVEFUNC_NOISE:
7978 case Q3WAVEFUNC_COUNT:
7981 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7982 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7983 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7984 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7985 case Q3WAVEFUNC_TRIANGLE:
7987 f = index - floor(index);
8000 f = parms[0] + parms[1] * f;
8001 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8002 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8006 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8013 matrix4x4_t matrix, temp;
8014 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8015 // it's better to have one huge fixup every 9 hours than gradual
8016 // degradation over time which looks consistently bad after many hours.
8018 // tcmod scroll in particular suffers from this degradation which can't be
8019 // effectively worked around even with floor() tricks because we don't
8020 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8021 // a workaround involving floor() would be incorrect anyway...
8022 shadertime = rsurface.shadertime;
8023 if (shadertime >= 32768.0f)
8024 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8025 switch(tcmod->tcmod)
8029 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8030 matrix = r_waterscrollmatrix;
8032 matrix = identitymatrix;
8034 case Q3TCMOD_ENTITYTRANSLATE:
8035 // this is used in Q3 to allow the gamecode to control texcoord
8036 // scrolling on the entity, which is not supported in darkplaces yet.
8037 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8039 case Q3TCMOD_ROTATE:
8040 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8041 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8042 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8045 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8047 case Q3TCMOD_SCROLL:
8048 // this particular tcmod is a "bug for bug" compatible one with regards to
8049 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8050 // specifically did the wrapping and so we must mimic that...
8051 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8052 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8053 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8055 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8056 w = (int) tcmod->parms[0];
8057 h = (int) tcmod->parms[1];
8058 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8060 idx = (int) floor(f * w * h);
8061 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8063 case Q3TCMOD_STRETCH:
8064 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8065 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8067 case Q3TCMOD_TRANSFORM:
8068 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8069 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8070 VectorSet(tcmat + 6, 0 , 0 , 1);
8071 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8072 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8074 case Q3TCMOD_TURBULENT:
8075 // this is handled in the RSurf_PrepareVertices function
8076 matrix = identitymatrix;
8080 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8083 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8085 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8086 char name[MAX_QPATH];
8087 skinframe_t *skinframe;
8088 unsigned char pixels[296*194];
8089 strlcpy(cache->name, skinname, sizeof(cache->name));
8090 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8091 if (developer_loading.integer)
8092 Con_Printf("loading %s\n", name);
8093 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8094 if (!skinframe || !skinframe->base)
8097 fs_offset_t filesize;
8099 f = FS_LoadFile(name, tempmempool, true, &filesize);
8102 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8103 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8107 cache->skinframe = skinframe;
8110 texture_t *R_GetCurrentTexture(texture_t *t)
8113 const entity_render_t *ent = rsurface.entity;
8114 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8115 q3shaderinfo_layer_tcmod_t *tcmod;
8117 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8118 return t->currentframe;
8119 t->update_lastrenderframe = r_textureframe;
8120 t->update_lastrenderentity = (void *)ent;
8122 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8123 t->camera_entity = ent->entitynumber;
8125 t->camera_entity = 0;
8127 // switch to an alternate material if this is a q1bsp animated material
8129 texture_t *texture = t;
8130 int s = rsurface.ent_skinnum;
8131 if ((unsigned int)s >= (unsigned int)model->numskins)
8133 if (model->skinscenes)
8135 if (model->skinscenes[s].framecount > 1)
8136 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8138 s = model->skinscenes[s].firstframe;
8141 t = t + s * model->num_surfaces;
8144 // use an alternate animation if the entity's frame is not 0,
8145 // and only if the texture has an alternate animation
8146 if (rsurface.ent_alttextures && t->anim_total[1])
8147 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8149 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8151 texture->currentframe = t;
8154 // update currentskinframe to be a qw skin or animation frame
8155 if (rsurface.ent_qwskin >= 0)
8157 i = rsurface.ent_qwskin;
8158 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8160 r_qwskincache_size = cl.maxclients;
8162 Mem_Free(r_qwskincache);
8163 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8165 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8166 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8167 t->currentskinframe = r_qwskincache[i].skinframe;
8168 if (t->currentskinframe == NULL)
8169 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8171 else if (t->numskinframes >= 2)
8172 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8173 if (t->backgroundnumskinframes >= 2)
8174 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8176 t->currentmaterialflags = t->basematerialflags;
8177 t->currentalpha = rsurface.colormod[3];
8178 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8179 t->currentalpha *= r_wateralpha.value;
8180 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8181 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8182 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8183 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8184 if (!(rsurface.ent_flags & RENDER_LIGHT))
8185 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8186 else if (FAKELIGHT_ENABLED)
8188 // no modellight if using fakelight for the map
8190 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8192 // pick a model lighting mode
8193 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8194 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8196 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8198 if (rsurface.ent_flags & RENDER_ADDITIVE)
8199 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8200 else if (t->currentalpha < 1)
8201 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8202 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8203 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8204 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8205 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8206 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8207 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8208 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8209 if (t->backgroundnumskinframes)
8210 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8211 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8213 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8214 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8217 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8218 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8220 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8221 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8223 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8224 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8226 // there is no tcmod
8227 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8229 t->currenttexmatrix = r_waterscrollmatrix;
8230 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8232 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8234 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8235 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8238 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8239 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8240 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8241 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8243 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8244 if (t->currentskinframe->qpixels)
8245 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8246 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8247 if (!t->basetexture)
8248 t->basetexture = r_texture_notexture;
8249 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8250 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8251 t->nmaptexture = t->currentskinframe->nmap;
8252 if (!t->nmaptexture)
8253 t->nmaptexture = r_texture_blanknormalmap;
8254 t->glosstexture = r_texture_black;
8255 t->glowtexture = t->currentskinframe->glow;
8256 t->fogtexture = t->currentskinframe->fog;
8257 t->reflectmasktexture = t->currentskinframe->reflect;
8258 if (t->backgroundnumskinframes)
8260 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8261 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8262 t->backgroundglosstexture = r_texture_black;
8263 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8264 if (!t->backgroundnmaptexture)
8265 t->backgroundnmaptexture = r_texture_blanknormalmap;
8266 // make sure that if glow is going to be used, both textures are not NULL
8267 if (!t->backgroundglowtexture && t->glowtexture)
8268 t->backgroundglowtexture = r_texture_black;
8269 if (!t->glowtexture && t->backgroundglowtexture)
8270 t->glowtexture = r_texture_black;
8274 t->backgroundbasetexture = r_texture_white;
8275 t->backgroundnmaptexture = r_texture_blanknormalmap;
8276 t->backgroundglosstexture = r_texture_black;
8277 t->backgroundglowtexture = NULL;
8279 t->specularpower = r_shadow_glossexponent.value;
8280 // TODO: store reference values for these in the texture?
8281 t->specularscale = 0;
8282 if (r_shadow_gloss.integer > 0)
8284 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8286 if (r_shadow_glossintensity.value > 0)
8288 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8289 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8290 t->specularscale = r_shadow_glossintensity.value;
8293 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8295 t->glosstexture = r_texture_white;
8296 t->backgroundglosstexture = r_texture_white;
8297 t->specularscale = r_shadow_gloss2intensity.value;
8298 t->specularpower = r_shadow_gloss2exponent.value;
8301 t->specularscale *= t->specularscalemod;
8302 t->specularpower *= t->specularpowermod;
8303 t->rtlightambient = 0;
8305 // lightmaps mode looks bad with dlights using actual texturing, so turn
8306 // off the colormap and glossmap, but leave the normalmap on as it still
8307 // accurately represents the shading involved
8308 if (gl_lightmaps.integer)
8310 t->basetexture = r_texture_grey128;
8311 t->pantstexture = r_texture_black;
8312 t->shirttexture = r_texture_black;
8313 if (gl_lightmaps.integer < 2)
8314 t->nmaptexture = r_texture_blanknormalmap;
8315 t->glosstexture = r_texture_black;
8316 t->glowtexture = NULL;
8317 t->fogtexture = NULL;
8318 t->reflectmasktexture = NULL;
8319 t->backgroundbasetexture = NULL;
8320 if (gl_lightmaps.integer < 2)
8321 t->backgroundnmaptexture = r_texture_blanknormalmap;
8322 t->backgroundglosstexture = r_texture_black;
8323 t->backgroundglowtexture = NULL;
8324 t->specularscale = 0;
8325 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8328 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8329 VectorClear(t->dlightcolor);
8330 t->currentnumlayers = 0;
8331 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8333 int blendfunc1, blendfunc2;
8335 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8337 blendfunc1 = GL_SRC_ALPHA;
8338 blendfunc2 = GL_ONE;
8340 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8342 blendfunc1 = GL_SRC_ALPHA;
8343 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8345 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8347 blendfunc1 = t->customblendfunc[0];
8348 blendfunc2 = t->customblendfunc[1];
8352 blendfunc1 = GL_ONE;
8353 blendfunc2 = GL_ZERO;
8355 // don't colormod evilblend textures
8356 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8357 VectorSet(t->lightmapcolor, 1, 1, 1);
8358 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8359 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8361 // fullbright is not affected by r_refdef.lightmapintensity
8362 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]);
8363 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8364 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]);
8365 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8366 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]);
8370 vec3_t ambientcolor;
8372 // set the color tint used for lights affecting this surface
8373 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8375 // q3bsp has no lightmap updates, so the lightstylevalue that
8376 // would normally be baked into the lightmap must be
8377 // applied to the color
8378 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8379 if (model->type == mod_brushq3)
8380 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8381 colorscale *= r_refdef.lightmapintensity;
8382 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8383 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8384 // basic lit geometry
8385 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]);
8386 // add pants/shirt if needed
8387 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8388 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]);
8389 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8390 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]);
8391 // now add ambient passes if needed
8392 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8394 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]);
8395 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8396 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]);
8397 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8398 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]);
8401 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8402 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]);
8403 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8405 // if this is opaque use alpha blend which will darken the earlier
8408 // if this is an alpha blended material, all the earlier passes
8409 // were darkened by fog already, so we only need to add the fog
8410 // color ontop through the fog mask texture
8412 // if this is an additive blended material, all the earlier passes
8413 // were darkened by fog already, and we should not add fog color
8414 // (because the background was not darkened, there is no fog color
8415 // that was lost behind it).
8416 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]);
8420 return t->currentframe;
8423 rsurfacestate_t rsurface;
8425 void RSurf_ActiveWorldEntity(void)
8427 dp_model_t *model = r_refdef.scene.worldmodel;
8428 //if (rsurface.entity == r_refdef.scene.worldentity)
8430 rsurface.entity = r_refdef.scene.worldentity;
8431 rsurface.skeleton = NULL;
8432 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8433 rsurface.ent_skinnum = 0;
8434 rsurface.ent_qwskin = -1;
8435 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8436 rsurface.shadertime = r_refdef.scene.time;
8437 rsurface.matrix = identitymatrix;
8438 rsurface.inversematrix = identitymatrix;
8439 rsurface.matrixscale = 1;
8440 rsurface.inversematrixscale = 1;
8441 R_EntityMatrix(&identitymatrix);
8442 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8443 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8444 rsurface.fograngerecip = r_refdef.fograngerecip;
8445 rsurface.fogheightfade = r_refdef.fogheightfade;
8446 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8447 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8448 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8449 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8450 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8451 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8452 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8453 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8454 rsurface.colormod[3] = 1;
8455 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);
8456 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8457 rsurface.frameblend[0].lerp = 1;
8458 rsurface.ent_alttextures = false;
8459 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8460 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8461 rsurface.entityskeletaltransform3x4 = NULL;
8462 rsurface.entityskeletaltransform3x4buffer = NULL;
8463 rsurface.entityskeletaltransform3x4offset = 0;
8464 rsurface.entityskeletaltransform3x4size = 0;;
8465 rsurface.entityskeletalnumtransforms = 0;
8466 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8467 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8468 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8469 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8470 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8471 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8472 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8473 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8475 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8476 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8477 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8478 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8479 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8480 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8481 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8482 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8484 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8485 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8486 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8487 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8488 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8489 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8490 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8491 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8492 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8493 rsurface.modelelement3i = model->surfmesh.data_element3i;
8494 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8495 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8496 rsurface.modelelement3s = model->surfmesh.data_element3s;
8497 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8498 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8499 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8500 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8501 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8502 rsurface.modelsurfaces = model->data_surfaces;
8503 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8504 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8505 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8506 rsurface.modelgeneratedvertex = false;
8507 rsurface.batchgeneratedvertex = false;
8508 rsurface.batchfirstvertex = 0;
8509 rsurface.batchnumvertices = 0;
8510 rsurface.batchfirsttriangle = 0;
8511 rsurface.batchnumtriangles = 0;
8512 rsurface.batchvertex3f = NULL;
8513 rsurface.batchvertex3f_vertexbuffer = NULL;
8514 rsurface.batchvertex3f_bufferoffset = 0;
8515 rsurface.batchsvector3f = NULL;
8516 rsurface.batchsvector3f_vertexbuffer = NULL;
8517 rsurface.batchsvector3f_bufferoffset = 0;
8518 rsurface.batchtvector3f = NULL;
8519 rsurface.batchtvector3f_vertexbuffer = NULL;
8520 rsurface.batchtvector3f_bufferoffset = 0;
8521 rsurface.batchnormal3f = NULL;
8522 rsurface.batchnormal3f_vertexbuffer = NULL;
8523 rsurface.batchnormal3f_bufferoffset = 0;
8524 rsurface.batchlightmapcolor4f = NULL;
8525 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8526 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8527 rsurface.batchtexcoordtexture2f = NULL;
8528 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8529 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8530 rsurface.batchtexcoordlightmap2f = NULL;
8531 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8532 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8533 rsurface.batchskeletalindex4ub = NULL;
8534 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8535 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8536 rsurface.batchskeletalweight4ub = NULL;
8537 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8538 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8539 rsurface.batchvertexmesh = NULL;
8540 rsurface.batchvertexmesh_vertexbuffer = NULL;
8541 rsurface.batchvertexmesh_bufferoffset = 0;
8542 rsurface.batchelement3i = NULL;
8543 rsurface.batchelement3i_indexbuffer = NULL;
8544 rsurface.batchelement3i_bufferoffset = 0;
8545 rsurface.batchelement3s = NULL;
8546 rsurface.batchelement3s_indexbuffer = NULL;
8547 rsurface.batchelement3s_bufferoffset = 0;
8548 rsurface.passcolor4f = NULL;
8549 rsurface.passcolor4f_vertexbuffer = NULL;
8550 rsurface.passcolor4f_bufferoffset = 0;
8551 rsurface.forcecurrenttextureupdate = false;
8554 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8556 dp_model_t *model = ent->model;
8557 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8559 rsurface.entity = (entity_render_t *)ent;
8560 rsurface.skeleton = ent->skeleton;
8561 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8562 rsurface.ent_skinnum = ent->skinnum;
8563 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;
8564 rsurface.ent_flags = ent->flags;
8565 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8566 rsurface.matrix = ent->matrix;
8567 rsurface.inversematrix = ent->inversematrix;
8568 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8569 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8570 R_EntityMatrix(&rsurface.matrix);
8571 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8572 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8573 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8574 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8575 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8576 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8577 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8578 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8579 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8580 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8581 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8582 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8583 rsurface.colormod[3] = ent->alpha;
8584 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8585 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8586 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8587 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8588 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8589 if (ent->model->brush.submodel && !prepass)
8591 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8592 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8594 // if the animcache code decided it should use the shader path, skip the deform step
8595 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8596 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8597 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8598 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8599 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8600 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8602 if (ent->animcache_vertex3f)
8604 r_refdef.stats[r_stat_batch_entitycache_count]++;
8605 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8606 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8607 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8608 rsurface.modelvertex3f = ent->animcache_vertex3f;
8609 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8610 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8611 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8612 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8613 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8614 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8615 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8616 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8617 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8618 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8619 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8620 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8621 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8622 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8624 else if (wanttangents)
8626 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8627 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8628 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8629 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8630 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8631 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8632 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8633 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8634 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8635 rsurface.modelvertexmesh = NULL;
8636 rsurface.modelvertexmesh_vertexbuffer = NULL;
8637 rsurface.modelvertexmesh_bufferoffset = 0;
8638 rsurface.modelvertex3f_vertexbuffer = NULL;
8639 rsurface.modelvertex3f_bufferoffset = 0;
8640 rsurface.modelvertex3f_vertexbuffer = 0;
8641 rsurface.modelvertex3f_bufferoffset = 0;
8642 rsurface.modelsvector3f_vertexbuffer = 0;
8643 rsurface.modelsvector3f_bufferoffset = 0;
8644 rsurface.modeltvector3f_vertexbuffer = 0;
8645 rsurface.modeltvector3f_bufferoffset = 0;
8646 rsurface.modelnormal3f_vertexbuffer = 0;
8647 rsurface.modelnormal3f_bufferoffset = 0;
8649 else if (wantnormals)
8651 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8652 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8653 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8654 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8655 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8656 rsurface.modelsvector3f = NULL;
8657 rsurface.modeltvector3f = NULL;
8658 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8659 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8660 rsurface.modelvertexmesh = NULL;
8661 rsurface.modelvertexmesh_vertexbuffer = NULL;
8662 rsurface.modelvertexmesh_bufferoffset = 0;
8663 rsurface.modelvertex3f_vertexbuffer = NULL;
8664 rsurface.modelvertex3f_bufferoffset = 0;
8665 rsurface.modelvertex3f_vertexbuffer = 0;
8666 rsurface.modelvertex3f_bufferoffset = 0;
8667 rsurface.modelsvector3f_vertexbuffer = 0;
8668 rsurface.modelsvector3f_bufferoffset = 0;
8669 rsurface.modeltvector3f_vertexbuffer = 0;
8670 rsurface.modeltvector3f_bufferoffset = 0;
8671 rsurface.modelnormal3f_vertexbuffer = 0;
8672 rsurface.modelnormal3f_bufferoffset = 0;
8676 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8677 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8678 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8679 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8680 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8681 rsurface.modelsvector3f = NULL;
8682 rsurface.modeltvector3f = NULL;
8683 rsurface.modelnormal3f = NULL;
8684 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8685 rsurface.modelvertexmesh = NULL;
8686 rsurface.modelvertexmesh_vertexbuffer = NULL;
8687 rsurface.modelvertexmesh_bufferoffset = 0;
8688 rsurface.modelvertex3f_vertexbuffer = NULL;
8689 rsurface.modelvertex3f_bufferoffset = 0;
8690 rsurface.modelvertex3f_vertexbuffer = 0;
8691 rsurface.modelvertex3f_bufferoffset = 0;
8692 rsurface.modelsvector3f_vertexbuffer = 0;
8693 rsurface.modelsvector3f_bufferoffset = 0;
8694 rsurface.modeltvector3f_vertexbuffer = 0;
8695 rsurface.modeltvector3f_bufferoffset = 0;
8696 rsurface.modelnormal3f_vertexbuffer = 0;
8697 rsurface.modelnormal3f_bufferoffset = 0;
8699 rsurface.modelgeneratedvertex = true;
8703 if (rsurface.entityskeletaltransform3x4)
8705 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8706 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8707 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8708 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8712 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8713 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8714 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8715 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8717 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8718 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8719 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8720 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8721 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8722 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8723 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8724 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8725 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8726 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8727 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8728 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8729 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8730 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8731 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8732 rsurface.modelgeneratedvertex = false;
8734 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8735 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8736 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8737 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8738 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8739 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8740 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8741 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8742 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8743 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8744 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8745 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8746 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8747 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8748 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8749 rsurface.modelelement3i = model->surfmesh.data_element3i;
8750 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8751 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8752 rsurface.modelelement3s = model->surfmesh.data_element3s;
8753 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8754 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8755 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8756 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8757 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8758 rsurface.modelsurfaces = model->data_surfaces;
8759 rsurface.batchgeneratedvertex = false;
8760 rsurface.batchfirstvertex = 0;
8761 rsurface.batchnumvertices = 0;
8762 rsurface.batchfirsttriangle = 0;
8763 rsurface.batchnumtriangles = 0;
8764 rsurface.batchvertex3f = NULL;
8765 rsurface.batchvertex3f_vertexbuffer = NULL;
8766 rsurface.batchvertex3f_bufferoffset = 0;
8767 rsurface.batchsvector3f = NULL;
8768 rsurface.batchsvector3f_vertexbuffer = NULL;
8769 rsurface.batchsvector3f_bufferoffset = 0;
8770 rsurface.batchtvector3f = NULL;
8771 rsurface.batchtvector3f_vertexbuffer = NULL;
8772 rsurface.batchtvector3f_bufferoffset = 0;
8773 rsurface.batchnormal3f = NULL;
8774 rsurface.batchnormal3f_vertexbuffer = NULL;
8775 rsurface.batchnormal3f_bufferoffset = 0;
8776 rsurface.batchlightmapcolor4f = NULL;
8777 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8778 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8779 rsurface.batchtexcoordtexture2f = NULL;
8780 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8781 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8782 rsurface.batchtexcoordlightmap2f = NULL;
8783 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8784 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8785 rsurface.batchskeletalindex4ub = NULL;
8786 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8787 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8788 rsurface.batchskeletalweight4ub = NULL;
8789 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8790 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8791 rsurface.batchvertexmesh = NULL;
8792 rsurface.batchvertexmesh_vertexbuffer = NULL;
8793 rsurface.batchvertexmesh_bufferoffset = 0;
8794 rsurface.batchelement3i = NULL;
8795 rsurface.batchelement3i_indexbuffer = NULL;
8796 rsurface.batchelement3i_bufferoffset = 0;
8797 rsurface.batchelement3s = NULL;
8798 rsurface.batchelement3s_indexbuffer = NULL;
8799 rsurface.batchelement3s_bufferoffset = 0;
8800 rsurface.passcolor4f = NULL;
8801 rsurface.passcolor4f_vertexbuffer = NULL;
8802 rsurface.passcolor4f_bufferoffset = 0;
8803 rsurface.forcecurrenttextureupdate = false;
8806 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)
8808 rsurface.entity = r_refdef.scene.worldentity;
8809 rsurface.skeleton = NULL;
8810 rsurface.ent_skinnum = 0;
8811 rsurface.ent_qwskin = -1;
8812 rsurface.ent_flags = entflags;
8813 rsurface.shadertime = r_refdef.scene.time - shadertime;
8814 rsurface.modelnumvertices = numvertices;
8815 rsurface.modelnumtriangles = numtriangles;
8816 rsurface.matrix = *matrix;
8817 rsurface.inversematrix = *inversematrix;
8818 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8819 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8820 R_EntityMatrix(&rsurface.matrix);
8821 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8822 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8823 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8824 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8825 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8826 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8827 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8828 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8829 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8830 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8831 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8832 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8833 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);
8834 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8835 rsurface.frameblend[0].lerp = 1;
8836 rsurface.ent_alttextures = false;
8837 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8838 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8839 rsurface.entityskeletaltransform3x4 = NULL;
8840 rsurface.entityskeletaltransform3x4buffer = NULL;
8841 rsurface.entityskeletaltransform3x4offset = 0;
8842 rsurface.entityskeletaltransform3x4size = 0;
8843 rsurface.entityskeletalnumtransforms = 0;
8844 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8845 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8846 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8847 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8850 rsurface.modelvertex3f = (float *)vertex3f;
8851 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8852 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8853 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8855 else if (wantnormals)
8857 rsurface.modelvertex3f = (float *)vertex3f;
8858 rsurface.modelsvector3f = NULL;
8859 rsurface.modeltvector3f = NULL;
8860 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8864 rsurface.modelvertex3f = (float *)vertex3f;
8865 rsurface.modelsvector3f = NULL;
8866 rsurface.modeltvector3f = NULL;
8867 rsurface.modelnormal3f = NULL;
8869 rsurface.modelvertexmesh = NULL;
8870 rsurface.modelvertexmesh_vertexbuffer = NULL;
8871 rsurface.modelvertexmesh_bufferoffset = 0;
8872 rsurface.modelvertex3f_vertexbuffer = 0;
8873 rsurface.modelvertex3f_bufferoffset = 0;
8874 rsurface.modelsvector3f_vertexbuffer = 0;
8875 rsurface.modelsvector3f_bufferoffset = 0;
8876 rsurface.modeltvector3f_vertexbuffer = 0;
8877 rsurface.modeltvector3f_bufferoffset = 0;
8878 rsurface.modelnormal3f_vertexbuffer = 0;
8879 rsurface.modelnormal3f_bufferoffset = 0;
8880 rsurface.modelgeneratedvertex = true;
8881 rsurface.modellightmapcolor4f = (float *)color4f;
8882 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8883 rsurface.modellightmapcolor4f_bufferoffset = 0;
8884 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8885 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8886 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8887 rsurface.modeltexcoordlightmap2f = NULL;
8888 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8889 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8890 rsurface.modelskeletalindex4ub = NULL;
8891 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8892 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8893 rsurface.modelskeletalweight4ub = NULL;
8894 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8895 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8896 rsurface.modelelement3i = (int *)element3i;
8897 rsurface.modelelement3i_indexbuffer = NULL;
8898 rsurface.modelelement3i_bufferoffset = 0;
8899 rsurface.modelelement3s = (unsigned short *)element3s;
8900 rsurface.modelelement3s_indexbuffer = NULL;
8901 rsurface.modelelement3s_bufferoffset = 0;
8902 rsurface.modellightmapoffsets = NULL;
8903 rsurface.modelsurfaces = NULL;
8904 rsurface.batchgeneratedvertex = false;
8905 rsurface.batchfirstvertex = 0;
8906 rsurface.batchnumvertices = 0;
8907 rsurface.batchfirsttriangle = 0;
8908 rsurface.batchnumtriangles = 0;
8909 rsurface.batchvertex3f = NULL;
8910 rsurface.batchvertex3f_vertexbuffer = NULL;
8911 rsurface.batchvertex3f_bufferoffset = 0;
8912 rsurface.batchsvector3f = NULL;
8913 rsurface.batchsvector3f_vertexbuffer = NULL;
8914 rsurface.batchsvector3f_bufferoffset = 0;
8915 rsurface.batchtvector3f = NULL;
8916 rsurface.batchtvector3f_vertexbuffer = NULL;
8917 rsurface.batchtvector3f_bufferoffset = 0;
8918 rsurface.batchnormal3f = NULL;
8919 rsurface.batchnormal3f_vertexbuffer = NULL;
8920 rsurface.batchnormal3f_bufferoffset = 0;
8921 rsurface.batchlightmapcolor4f = NULL;
8922 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8923 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8924 rsurface.batchtexcoordtexture2f = NULL;
8925 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8926 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8927 rsurface.batchtexcoordlightmap2f = NULL;
8928 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8929 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8930 rsurface.batchskeletalindex4ub = NULL;
8931 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8932 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8933 rsurface.batchskeletalweight4ub = NULL;
8934 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8935 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8936 rsurface.batchvertexmesh = NULL;
8937 rsurface.batchvertexmesh_vertexbuffer = NULL;
8938 rsurface.batchvertexmesh_bufferoffset = 0;
8939 rsurface.batchelement3i = NULL;
8940 rsurface.batchelement3i_indexbuffer = NULL;
8941 rsurface.batchelement3i_bufferoffset = 0;
8942 rsurface.batchelement3s = NULL;
8943 rsurface.batchelement3s_indexbuffer = NULL;
8944 rsurface.batchelement3s_bufferoffset = 0;
8945 rsurface.passcolor4f = NULL;
8946 rsurface.passcolor4f_vertexbuffer = NULL;
8947 rsurface.passcolor4f_bufferoffset = 0;
8948 rsurface.forcecurrenttextureupdate = true;
8950 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8952 if ((wantnormals || wanttangents) && !normal3f)
8954 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8955 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8957 if (wanttangents && !svector3f)
8959 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8960 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8961 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8966 float RSurf_FogPoint(const float *v)
8968 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8969 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8970 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8971 float FogHeightFade = r_refdef.fogheightfade;
8973 unsigned int fogmasktableindex;
8974 if (r_refdef.fogplaneviewabove)
8975 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8977 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8978 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8979 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8982 float RSurf_FogVertex(const float *v)
8984 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8985 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8986 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8987 float FogHeightFade = rsurface.fogheightfade;
8989 unsigned int fogmasktableindex;
8990 if (r_refdef.fogplaneviewabove)
8991 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8993 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8994 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8995 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8998 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9001 for (i = 0;i < numelements;i++)
9002 outelement3i[i] = inelement3i[i] + adjust;
9005 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9006 extern cvar_t gl_vbo;
9007 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9015 int surfacefirsttriangle;
9016 int surfacenumtriangles;
9017 int surfacefirstvertex;
9018 int surfaceendvertex;
9019 int surfacenumvertices;
9020 int batchnumsurfaces = texturenumsurfaces;
9021 int batchnumvertices;
9022 int batchnumtriangles;
9026 qboolean dynamicvertex;
9030 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9033 q3shaderinfo_deform_t *deform;
9034 const msurface_t *surface, *firstsurface;
9035 r_vertexmesh_t *vertexmesh;
9036 if (!texturenumsurfaces)
9038 // find vertex range of this surface batch
9040 firstsurface = texturesurfacelist[0];
9041 firsttriangle = firstsurface->num_firsttriangle;
9042 batchnumvertices = 0;
9043 batchnumtriangles = 0;
9044 firstvertex = endvertex = firstsurface->num_firstvertex;
9045 for (i = 0;i < texturenumsurfaces;i++)
9047 surface = texturesurfacelist[i];
9048 if (surface != firstsurface + i)
9050 surfacefirstvertex = surface->num_firstvertex;
9051 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9052 surfacenumvertices = surface->num_vertices;
9053 surfacenumtriangles = surface->num_triangles;
9054 if (firstvertex > surfacefirstvertex)
9055 firstvertex = surfacefirstvertex;
9056 if (endvertex < surfaceendvertex)
9057 endvertex = surfaceendvertex;
9058 batchnumvertices += surfacenumvertices;
9059 batchnumtriangles += surfacenumtriangles;
9062 r_refdef.stats[r_stat_batch_batches]++;
9064 r_refdef.stats[r_stat_batch_withgaps]++;
9065 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9066 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9067 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9069 // we now know the vertex range used, and if there are any gaps in it
9070 rsurface.batchfirstvertex = firstvertex;
9071 rsurface.batchnumvertices = endvertex - firstvertex;
9072 rsurface.batchfirsttriangle = firsttriangle;
9073 rsurface.batchnumtriangles = batchnumtriangles;
9075 // this variable holds flags for which properties have been updated that
9076 // may require regenerating vertexmesh array...
9079 // check if any dynamic vertex processing must occur
9080 dynamicvertex = false;
9082 // a cvar to force the dynamic vertex path to be taken, for debugging
9083 if (r_batch_debugdynamicvertexpath.integer)
9087 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9088 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9089 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9090 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9092 dynamicvertex = true;
9095 // if there is a chance of animated vertex colors, it's a dynamic batch
9096 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9100 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9101 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9102 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9103 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9105 dynamicvertex = true;
9106 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9109 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9111 switch (deform->deform)
9114 case Q3DEFORM_PROJECTIONSHADOW:
9115 case Q3DEFORM_TEXT0:
9116 case Q3DEFORM_TEXT1:
9117 case Q3DEFORM_TEXT2:
9118 case Q3DEFORM_TEXT3:
9119 case Q3DEFORM_TEXT4:
9120 case Q3DEFORM_TEXT5:
9121 case Q3DEFORM_TEXT6:
9122 case Q3DEFORM_TEXT7:
9125 case Q3DEFORM_AUTOSPRITE:
9128 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9129 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9130 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9131 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9133 dynamicvertex = true;
9134 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9135 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9137 case Q3DEFORM_AUTOSPRITE2:
9140 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9141 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9142 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9143 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9145 dynamicvertex = true;
9146 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9147 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9149 case Q3DEFORM_NORMAL:
9152 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9153 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9154 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9155 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9157 dynamicvertex = true;
9158 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9159 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9162 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9163 break; // if wavefunc is a nop, ignore this transform
9166 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9167 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9168 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9169 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9171 dynamicvertex = true;
9172 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9173 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9175 case Q3DEFORM_BULGE:
9178 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9179 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9180 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9181 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9183 dynamicvertex = true;
9184 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9185 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9188 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9189 break; // if wavefunc is a nop, ignore this transform
9192 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9193 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9194 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9195 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9197 dynamicvertex = true;
9198 batchneed |= BATCHNEED_ARRAY_VERTEX;
9199 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9203 switch(rsurface.texture->tcgen.tcgen)
9206 case Q3TCGEN_TEXTURE:
9208 case Q3TCGEN_LIGHTMAP:
9211 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9212 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9213 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9214 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9216 dynamicvertex = true;
9217 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9218 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9220 case Q3TCGEN_VECTOR:
9223 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9224 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9225 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9226 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9228 dynamicvertex = true;
9229 batchneed |= BATCHNEED_ARRAY_VERTEX;
9230 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9232 case Q3TCGEN_ENVIRONMENT:
9235 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9236 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9237 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9238 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9240 dynamicvertex = true;
9241 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9242 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9245 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9249 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9250 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9251 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9252 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9254 dynamicvertex = true;
9255 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9256 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9259 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9263 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9264 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9265 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9266 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9268 dynamicvertex = true;
9269 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9272 // when the model data has no vertex buffer (dynamic mesh), we need to
9274 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9275 batchneed |= BATCHNEED_NOGAPS;
9277 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9278 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9279 // we ensure this by treating the vertex batch as dynamic...
9280 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9284 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9285 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9286 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9287 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9289 dynamicvertex = true;
9294 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9295 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9296 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9297 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9298 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9299 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9300 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9301 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9304 // if needsupdate, we have to do a dynamic vertex batch for sure
9305 if (needsupdate & batchneed)
9309 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9310 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9311 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9312 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9314 dynamicvertex = true;
9317 // see if we need to build vertexmesh from arrays
9318 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9322 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9323 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9324 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9325 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9327 dynamicvertex = true;
9330 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9331 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9332 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9334 rsurface.batchvertex3f = rsurface.modelvertex3f;
9335 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9336 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9337 rsurface.batchsvector3f = rsurface.modelsvector3f;
9338 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9339 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9340 rsurface.batchtvector3f = rsurface.modeltvector3f;
9341 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9342 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9343 rsurface.batchnormal3f = rsurface.modelnormal3f;
9344 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9345 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9346 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9347 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9348 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9349 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9350 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9351 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9352 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9353 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9354 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9355 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9356 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9357 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9358 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9359 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9360 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9361 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9362 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9363 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9364 rsurface.batchelement3i = rsurface.modelelement3i;
9365 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9366 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9367 rsurface.batchelement3s = rsurface.modelelement3s;
9368 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9369 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9370 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9371 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9372 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9373 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9374 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9376 // if any dynamic vertex processing has to occur in software, we copy the
9377 // entire surface list together before processing to rebase the vertices
9378 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9380 // if any gaps exist and we do not have a static vertex buffer, we have to
9381 // copy the surface list together to avoid wasting upload bandwidth on the
9382 // vertices in the gaps.
9384 // if gaps exist and we have a static vertex buffer, we can choose whether
9385 // to combine the index buffer ranges into one dynamic index buffer or
9386 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9388 // in many cases the batch is reduced to one draw call.
9390 rsurface.batchmultidraw = false;
9391 rsurface.batchmultidrawnumsurfaces = 0;
9392 rsurface.batchmultidrawsurfacelist = NULL;
9396 // static vertex data, just set pointers...
9397 rsurface.batchgeneratedvertex = false;
9398 // if there are gaps, we want to build a combined index buffer,
9399 // otherwise use the original static buffer with an appropriate offset
9402 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9403 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9404 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9405 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9406 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9408 rsurface.batchmultidraw = true;
9409 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9410 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9413 // build a new triangle elements array for this batch
9414 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9415 rsurface.batchfirsttriangle = 0;
9417 for (i = 0;i < texturenumsurfaces;i++)
9419 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9420 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9421 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9422 numtriangles += surfacenumtriangles;
9424 rsurface.batchelement3i_indexbuffer = NULL;
9425 rsurface.batchelement3i_bufferoffset = 0;
9426 rsurface.batchelement3s = NULL;
9427 rsurface.batchelement3s_indexbuffer = NULL;
9428 rsurface.batchelement3s_bufferoffset = 0;
9429 if (endvertex <= 65536)
9431 // make a 16bit (unsigned short) index array if possible
9432 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9433 for (i = 0;i < numtriangles*3;i++)
9434 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9436 // upload buffer data for the copytriangles batch
9437 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9439 if (rsurface.batchelement3s)
9440 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9441 else if (rsurface.batchelement3i)
9442 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9447 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9448 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9449 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9450 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9455 // something needs software processing, do it for real...
9456 // we only directly handle separate array data in this case and then
9457 // generate interleaved data if needed...
9458 rsurface.batchgeneratedvertex = true;
9459 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9460 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9461 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9462 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9464 // now copy the vertex data into a combined array and make an index array
9465 // (this is what Quake3 does all the time)
9466 // we also apply any skeletal animation here that would have been done in
9467 // the vertex shader, because most of the dynamic vertex animation cases
9468 // need actual vertex positions and normals
9469 //if (dynamicvertex)
9471 rsurface.batchvertexmesh = NULL;
9472 rsurface.batchvertexmesh_vertexbuffer = NULL;
9473 rsurface.batchvertexmesh_bufferoffset = 0;
9474 rsurface.batchvertex3f = NULL;
9475 rsurface.batchvertex3f_vertexbuffer = NULL;
9476 rsurface.batchvertex3f_bufferoffset = 0;
9477 rsurface.batchsvector3f = NULL;
9478 rsurface.batchsvector3f_vertexbuffer = NULL;
9479 rsurface.batchsvector3f_bufferoffset = 0;
9480 rsurface.batchtvector3f = NULL;
9481 rsurface.batchtvector3f_vertexbuffer = NULL;
9482 rsurface.batchtvector3f_bufferoffset = 0;
9483 rsurface.batchnormal3f = NULL;
9484 rsurface.batchnormal3f_vertexbuffer = NULL;
9485 rsurface.batchnormal3f_bufferoffset = 0;
9486 rsurface.batchlightmapcolor4f = NULL;
9487 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9488 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9489 rsurface.batchtexcoordtexture2f = NULL;
9490 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9491 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9492 rsurface.batchtexcoordlightmap2f = NULL;
9493 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9494 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9495 rsurface.batchskeletalindex4ub = NULL;
9496 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9497 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9498 rsurface.batchskeletalweight4ub = NULL;
9499 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9500 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9501 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9502 rsurface.batchelement3i_indexbuffer = NULL;
9503 rsurface.batchelement3i_bufferoffset = 0;
9504 rsurface.batchelement3s = NULL;
9505 rsurface.batchelement3s_indexbuffer = NULL;
9506 rsurface.batchelement3s_bufferoffset = 0;
9507 rsurface.batchskeletaltransform3x4buffer = NULL;
9508 rsurface.batchskeletaltransform3x4offset = 0;
9509 rsurface.batchskeletaltransform3x4size = 0;
9510 // we'll only be setting up certain arrays as needed
9511 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9512 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9513 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9514 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9515 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9516 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9517 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9519 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9520 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9522 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9523 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9524 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9525 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9526 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9527 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9528 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9530 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9531 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9535 for (i = 0;i < texturenumsurfaces;i++)
9537 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9538 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9539 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9540 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9541 // copy only the data requested
9542 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9543 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9544 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9546 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9548 if (rsurface.batchvertex3f)
9549 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9551 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9553 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9555 if (rsurface.modelnormal3f)
9556 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9558 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9560 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9562 if (rsurface.modelsvector3f)
9564 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9565 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9569 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9570 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9573 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9575 if (rsurface.modellightmapcolor4f)
9576 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9578 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9580 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9582 if (rsurface.modeltexcoordtexture2f)
9583 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9585 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9587 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9589 if (rsurface.modeltexcoordlightmap2f)
9590 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9592 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9594 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9596 if (rsurface.modelskeletalindex4ub)
9598 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9599 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9603 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9604 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9605 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9606 for (j = 0;j < surfacenumvertices;j++)
9611 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9612 numvertices += surfacenumvertices;
9613 numtriangles += surfacenumtriangles;
9616 // generate a 16bit index array as well if possible
9617 // (in general, dynamic batches fit)
9618 if (numvertices <= 65536)
9620 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9621 for (i = 0;i < numtriangles*3;i++)
9622 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9625 // since we've copied everything, the batch now starts at 0
9626 rsurface.batchfirstvertex = 0;
9627 rsurface.batchnumvertices = batchnumvertices;
9628 rsurface.batchfirsttriangle = 0;
9629 rsurface.batchnumtriangles = batchnumtriangles;
9632 // apply skeletal animation that would have been done in the vertex shader
9633 if (rsurface.batchskeletaltransform3x4)
9635 const unsigned char *si;
9636 const unsigned char *sw;
9638 const float *b = rsurface.batchskeletaltransform3x4;
9639 float *vp, *vs, *vt, *vn;
9641 float m[3][4], n[3][4];
9642 float tp[3], ts[3], tt[3], tn[3];
9643 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9644 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9645 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9646 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9647 si = rsurface.batchskeletalindex4ub;
9648 sw = rsurface.batchskeletalweight4ub;
9649 vp = rsurface.batchvertex3f;
9650 vs = rsurface.batchsvector3f;
9651 vt = rsurface.batchtvector3f;
9652 vn = rsurface.batchnormal3f;
9653 memset(m[0], 0, sizeof(m));
9654 memset(n[0], 0, sizeof(n));
9655 for (i = 0;i < batchnumvertices;i++)
9657 t[0] = b + si[0]*12;
9660 // common case - only one matrix
9674 else if (sw[2] + sw[3])
9677 t[1] = b + si[1]*12;
9678 t[2] = b + si[2]*12;
9679 t[3] = b + si[3]*12;
9680 w[0] = sw[0] * (1.0f / 255.0f);
9681 w[1] = sw[1] * (1.0f / 255.0f);
9682 w[2] = sw[2] * (1.0f / 255.0f);
9683 w[3] = sw[3] * (1.0f / 255.0f);
9684 // blend the matrices
9685 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9686 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9687 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9688 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9689 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9690 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9691 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9692 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9693 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9694 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9695 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9696 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9701 t[1] = b + si[1]*12;
9702 w[0] = sw[0] * (1.0f / 255.0f);
9703 w[1] = sw[1] * (1.0f / 255.0f);
9704 // blend the matrices
9705 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9706 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9707 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9708 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9709 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9710 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9711 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9712 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9713 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9714 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9715 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9716 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9720 // modify the vertex
9722 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9723 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9724 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9728 // the normal transformation matrix is a set of cross products...
9729 CrossProduct(m[1], m[2], n[0]);
9730 CrossProduct(m[2], m[0], n[1]);
9731 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9733 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9734 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9735 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9736 VectorNormalize(vn);
9741 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9742 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9743 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9744 VectorNormalize(vs);
9747 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9748 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9749 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9750 VectorNormalize(vt);
9755 rsurface.batchskeletaltransform3x4 = NULL;
9756 rsurface.batchskeletalnumtransforms = 0;
9759 // q1bsp surfaces rendered in vertex color mode have to have colors
9760 // calculated based on lightstyles
9761 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9763 // generate color arrays for the surfaces in this list
9768 const unsigned char *lm;
9769 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9770 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9771 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9773 for (i = 0;i < texturenumsurfaces;i++)
9775 surface = texturesurfacelist[i];
9776 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9777 surfacenumvertices = surface->num_vertices;
9778 if (surface->lightmapinfo->samples)
9780 for (j = 0;j < surfacenumvertices;j++)
9782 lm = surface->lightmapinfo->samples + offsets[j];
9783 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9784 VectorScale(lm, scale, c);
9785 if (surface->lightmapinfo->styles[1] != 255)
9787 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9789 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9790 VectorMA(c, scale, lm, c);
9791 if (surface->lightmapinfo->styles[2] != 255)
9794 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9795 VectorMA(c, scale, lm, c);
9796 if (surface->lightmapinfo->styles[3] != 255)
9799 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9800 VectorMA(c, scale, lm, c);
9807 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);
9813 for (j = 0;j < surfacenumvertices;j++)
9815 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9822 // if vertices are deformed (sprite flares and things in maps, possibly
9823 // water waves, bulges and other deformations), modify the copied vertices
9825 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9827 switch (deform->deform)
9830 case Q3DEFORM_PROJECTIONSHADOW:
9831 case Q3DEFORM_TEXT0:
9832 case Q3DEFORM_TEXT1:
9833 case Q3DEFORM_TEXT2:
9834 case Q3DEFORM_TEXT3:
9835 case Q3DEFORM_TEXT4:
9836 case Q3DEFORM_TEXT5:
9837 case Q3DEFORM_TEXT6:
9838 case Q3DEFORM_TEXT7:
9841 case Q3DEFORM_AUTOSPRITE:
9842 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9843 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9844 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9845 VectorNormalize(newforward);
9846 VectorNormalize(newright);
9847 VectorNormalize(newup);
9848 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9849 // rsurface.batchvertex3f_vertexbuffer = NULL;
9850 // rsurface.batchvertex3f_bufferoffset = 0;
9851 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9852 // rsurface.batchsvector3f_vertexbuffer = NULL;
9853 // rsurface.batchsvector3f_bufferoffset = 0;
9854 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9855 // rsurface.batchtvector3f_vertexbuffer = NULL;
9856 // rsurface.batchtvector3f_bufferoffset = 0;
9857 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9858 // rsurface.batchnormal3f_vertexbuffer = NULL;
9859 // rsurface.batchnormal3f_bufferoffset = 0;
9860 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9861 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9862 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9863 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9864 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);
9865 // a single autosprite surface can contain multiple sprites...
9866 for (j = 0;j < batchnumvertices - 3;j += 4)
9868 VectorClear(center);
9869 for (i = 0;i < 4;i++)
9870 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9871 VectorScale(center, 0.25f, center);
9872 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9873 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9874 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9875 for (i = 0;i < 4;i++)
9877 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9878 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9881 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9882 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9883 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);
9885 case Q3DEFORM_AUTOSPRITE2:
9886 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9887 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9888 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9889 VectorNormalize(newforward);
9890 VectorNormalize(newright);
9891 VectorNormalize(newup);
9892 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9893 // rsurface.batchvertex3f_vertexbuffer = NULL;
9894 // rsurface.batchvertex3f_bufferoffset = 0;
9896 const float *v1, *v2;
9906 memset(shortest, 0, sizeof(shortest));
9907 // a single autosprite surface can contain multiple sprites...
9908 for (j = 0;j < batchnumvertices - 3;j += 4)
9910 VectorClear(center);
9911 for (i = 0;i < 4;i++)
9912 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9913 VectorScale(center, 0.25f, center);
9914 // find the two shortest edges, then use them to define the
9915 // axis vectors for rotating around the central axis
9916 for (i = 0;i < 6;i++)
9918 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9919 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9920 l = VectorDistance2(v1, v2);
9921 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9923 l += (1.0f / 1024.0f);
9924 if (shortest[0].length2 > l || i == 0)
9926 shortest[1] = shortest[0];
9927 shortest[0].length2 = l;
9928 shortest[0].v1 = v1;
9929 shortest[0].v2 = v2;
9931 else if (shortest[1].length2 > l || i == 1)
9933 shortest[1].length2 = l;
9934 shortest[1].v1 = v1;
9935 shortest[1].v2 = v2;
9938 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9939 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9940 // this calculates the right vector from the shortest edge
9941 // and the up vector from the edge midpoints
9942 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9943 VectorNormalize(right);
9944 VectorSubtract(end, start, up);
9945 VectorNormalize(up);
9946 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9947 VectorSubtract(rsurface.localvieworigin, center, forward);
9948 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9949 VectorNegate(forward, forward);
9950 VectorReflect(forward, 0, up, forward);
9951 VectorNormalize(forward);
9952 CrossProduct(up, forward, newright);
9953 VectorNormalize(newright);
9954 // rotate the quad around the up axis vector, this is made
9955 // especially easy by the fact we know the quad is flat,
9956 // so we only have to subtract the center position and
9957 // measure distance along the right vector, and then
9958 // multiply that by the newright vector and add back the
9960 // we also need to subtract the old position to undo the
9961 // displacement from the center, which we do with a
9962 // DotProduct, the subtraction/addition of center is also
9963 // optimized into DotProducts here
9964 l = DotProduct(right, center);
9965 for (i = 0;i < 4;i++)
9967 v1 = rsurface.batchvertex3f + 3*(j+i);
9968 f = DotProduct(right, v1) - l;
9969 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9973 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9975 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9976 // rsurface.batchnormal3f_vertexbuffer = NULL;
9977 // rsurface.batchnormal3f_bufferoffset = 0;
9978 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9980 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9982 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9983 // rsurface.batchsvector3f_vertexbuffer = NULL;
9984 // rsurface.batchsvector3f_bufferoffset = 0;
9985 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9986 // rsurface.batchtvector3f_vertexbuffer = NULL;
9987 // rsurface.batchtvector3f_bufferoffset = 0;
9988 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);
9991 case Q3DEFORM_NORMAL:
9992 // deform the normals to make reflections wavey
9993 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9994 rsurface.batchnormal3f_vertexbuffer = NULL;
9995 rsurface.batchnormal3f_bufferoffset = 0;
9996 for (j = 0;j < batchnumvertices;j++)
9999 float *normal = rsurface.batchnormal3f + 3*j;
10000 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10001 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10002 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10003 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10004 VectorNormalize(normal);
10006 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10008 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10009 // rsurface.batchsvector3f_vertexbuffer = NULL;
10010 // rsurface.batchsvector3f_bufferoffset = 0;
10011 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10012 // rsurface.batchtvector3f_vertexbuffer = NULL;
10013 // rsurface.batchtvector3f_bufferoffset = 0;
10014 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);
10017 case Q3DEFORM_WAVE:
10018 // deform vertex array to make wavey water and flags and such
10019 waveparms[0] = deform->waveparms[0];
10020 waveparms[1] = deform->waveparms[1];
10021 waveparms[2] = deform->waveparms[2];
10022 waveparms[3] = deform->waveparms[3];
10023 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10024 break; // if wavefunc is a nop, don't make a dynamic vertex array
10025 // this is how a divisor of vertex influence on deformation
10026 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10027 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10028 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10029 // rsurface.batchvertex3f_vertexbuffer = NULL;
10030 // rsurface.batchvertex3f_bufferoffset = 0;
10031 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10032 // rsurface.batchnormal3f_vertexbuffer = NULL;
10033 // rsurface.batchnormal3f_bufferoffset = 0;
10034 for (j = 0;j < batchnumvertices;j++)
10036 // if the wavefunc depends on time, evaluate it per-vertex
10039 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10040 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10042 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10044 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10045 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10046 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10048 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10049 // rsurface.batchsvector3f_vertexbuffer = NULL;
10050 // rsurface.batchsvector3f_bufferoffset = 0;
10051 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10052 // rsurface.batchtvector3f_vertexbuffer = NULL;
10053 // rsurface.batchtvector3f_bufferoffset = 0;
10054 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);
10057 case Q3DEFORM_BULGE:
10058 // deform vertex array to make the surface have moving bulges
10059 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10060 // rsurface.batchvertex3f_vertexbuffer = NULL;
10061 // rsurface.batchvertex3f_bufferoffset = 0;
10062 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10063 // rsurface.batchnormal3f_vertexbuffer = NULL;
10064 // rsurface.batchnormal3f_bufferoffset = 0;
10065 for (j = 0;j < batchnumvertices;j++)
10067 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10068 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10070 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10071 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10072 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10074 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10075 // rsurface.batchsvector3f_vertexbuffer = NULL;
10076 // rsurface.batchsvector3f_bufferoffset = 0;
10077 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10078 // rsurface.batchtvector3f_vertexbuffer = NULL;
10079 // rsurface.batchtvector3f_bufferoffset = 0;
10080 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);
10083 case Q3DEFORM_MOVE:
10084 // deform vertex array
10085 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10086 break; // if wavefunc is a nop, don't make a dynamic vertex array
10087 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10088 VectorScale(deform->parms, scale, waveparms);
10089 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10090 // rsurface.batchvertex3f_vertexbuffer = NULL;
10091 // rsurface.batchvertex3f_bufferoffset = 0;
10092 for (j = 0;j < batchnumvertices;j++)
10093 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10098 if (rsurface.batchtexcoordtexture2f)
10100 // generate texcoords based on the chosen texcoord source
10101 switch(rsurface.texture->tcgen.tcgen)
10104 case Q3TCGEN_TEXTURE:
10106 case Q3TCGEN_LIGHTMAP:
10107 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10108 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10109 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10110 if (rsurface.batchtexcoordlightmap2f)
10111 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10113 case Q3TCGEN_VECTOR:
10114 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10115 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10116 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10117 for (j = 0;j < batchnumvertices;j++)
10119 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10120 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10123 case Q3TCGEN_ENVIRONMENT:
10124 // make environment reflections using a spheremap
10125 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10126 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10127 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10128 for (j = 0;j < batchnumvertices;j++)
10130 // identical to Q3A's method, but executed in worldspace so
10131 // carried models can be shiny too
10133 float viewer[3], d, reflected[3], worldreflected[3];
10135 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10136 // VectorNormalize(viewer);
10138 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10140 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10141 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10142 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10143 // note: this is proportinal to viewer, so we can normalize later
10145 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10146 VectorNormalize(worldreflected);
10148 // note: this sphere map only uses world x and z!
10149 // so positive and negative y will LOOK THE SAME.
10150 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10151 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10155 // the only tcmod that needs software vertex processing is turbulent, so
10156 // check for it here and apply the changes if needed
10157 // and we only support that as the first one
10158 // (handling a mixture of turbulent and other tcmods would be problematic
10159 // without punting it entirely to a software path)
10160 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10162 amplitude = rsurface.texture->tcmods[0].parms[1];
10163 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10164 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10165 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10166 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10167 for (j = 0;j < batchnumvertices;j++)
10169 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);
10170 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10175 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10177 // convert the modified arrays to vertex structs
10178 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10179 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10180 // rsurface.batchvertexmesh_bufferoffset = 0;
10181 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10182 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10183 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10184 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10185 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10186 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10187 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10189 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10191 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10192 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10195 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10196 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10197 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10198 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10199 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10200 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10201 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10202 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10203 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10204 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10206 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10208 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10209 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10214 // upload buffer data for the dynamic batch
10215 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10217 if (rsurface.batchvertexmesh)
10218 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10221 if (rsurface.batchvertex3f)
10222 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10223 if (rsurface.batchsvector3f)
10224 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10225 if (rsurface.batchtvector3f)
10226 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10227 if (rsurface.batchnormal3f)
10228 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10229 if (rsurface.batchlightmapcolor4f)
10230 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10231 if (rsurface.batchtexcoordtexture2f)
10232 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10233 if (rsurface.batchtexcoordlightmap2f)
10234 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10235 if (rsurface.batchskeletalindex4ub)
10236 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10237 if (rsurface.batchskeletalweight4ub)
10238 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10240 if (rsurface.batchelement3s)
10241 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10242 else if (rsurface.batchelement3i)
10243 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10247 void RSurf_DrawBatch(void)
10249 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10250 // through the pipeline, killing it earlier in the pipeline would have
10251 // per-surface overhead rather than per-batch overhead, so it's best to
10252 // reject it here, before it hits glDraw.
10253 if (rsurface.batchnumtriangles == 0)
10256 // batch debugging code
10257 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10263 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10264 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10267 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10269 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10271 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10272 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);
10279 if (rsurface.batchmultidraw)
10281 // issue multiple draws rather than copying index data
10282 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10283 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10284 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10285 for (i = 0;i < numsurfaces;)
10287 // combine consecutive surfaces as one draw
10288 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10289 if (surfacelist[j] != surfacelist[k] + 1)
10291 firstvertex = surfacelist[i]->num_firstvertex;
10292 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10293 firsttriangle = surfacelist[i]->num_firsttriangle;
10294 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10295 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);
10301 // there is only one consecutive run of index data (may have been combined)
10302 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);
10306 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10308 // pick the closest matching water plane
10309 int planeindex, vertexindex, bestplaneindex = -1;
10313 r_waterstate_waterplane_t *p;
10314 qboolean prepared = false;
10316 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10318 if(p->camera_entity != rsurface.texture->camera_entity)
10323 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10325 if(rsurface.batchnumvertices == 0)
10328 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10330 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10331 d += fabs(PlaneDiff(vert, &p->plane));
10333 if (bestd > d || bestplaneindex < 0)
10336 bestplaneindex = planeindex;
10339 return bestplaneindex;
10340 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10341 // this situation though, as it might be better to render single larger
10342 // batches with useless stuff (backface culled for example) than to
10343 // render multiple smaller batches
10346 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10349 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10350 rsurface.passcolor4f_vertexbuffer = 0;
10351 rsurface.passcolor4f_bufferoffset = 0;
10352 for (i = 0;i < rsurface.batchnumvertices;i++)
10353 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10356 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10363 if (rsurface.passcolor4f)
10365 // generate color arrays
10366 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10367 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10368 rsurface.passcolor4f_vertexbuffer = 0;
10369 rsurface.passcolor4f_bufferoffset = 0;
10370 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)
10372 f = RSurf_FogVertex(v);
10381 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10382 rsurface.passcolor4f_vertexbuffer = 0;
10383 rsurface.passcolor4f_bufferoffset = 0;
10384 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10386 f = RSurf_FogVertex(v);
10395 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
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, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10410 f = RSurf_FogVertex(v);
10411 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10412 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10413 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10418 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10423 if (!rsurface.passcolor4f)
10425 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10426 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10427 rsurface.passcolor4f_vertexbuffer = 0;
10428 rsurface.passcolor4f_bufferoffset = 0;
10429 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10438 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10443 if (!rsurface.passcolor4f)
10445 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10446 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10447 rsurface.passcolor4f_vertexbuffer = 0;
10448 rsurface.passcolor4f_bufferoffset = 0;
10449 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10451 c2[0] = c[0] + r_refdef.scene.ambient;
10452 c2[1] = c[1] + r_refdef.scene.ambient;
10453 c2[2] = c[2] + r_refdef.scene.ambient;
10458 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10461 rsurface.passcolor4f = NULL;
10462 rsurface.passcolor4f_vertexbuffer = 0;
10463 rsurface.passcolor4f_bufferoffset = 0;
10464 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10465 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10466 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10467 GL_Color(r, g, b, a);
10468 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10469 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10470 R_Mesh_TexMatrix(0, NULL);
10474 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10476 // TODO: optimize applyfog && applycolor case
10477 // just apply fog if necessary, and tint the fog color array if necessary
10478 rsurface.passcolor4f = NULL;
10479 rsurface.passcolor4f_vertexbuffer = 0;
10480 rsurface.passcolor4f_bufferoffset = 0;
10481 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10482 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10483 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10484 GL_Color(r, g, b, a);
10488 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10491 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10492 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10493 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10494 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10495 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10496 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10497 GL_Color(r, g, b, a);
10501 static void RSurf_DrawBatch_GL11_ClampColor(void)
10506 if (!rsurface.passcolor4f)
10508 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10510 c2[0] = bound(0.0f, c1[0], 1.0f);
10511 c2[1] = bound(0.0f, c1[1], 1.0f);
10512 c2[2] = bound(0.0f, c1[2], 1.0f);
10513 c2[3] = bound(0.0f, c1[3], 1.0f);
10517 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10527 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10528 rsurface.passcolor4f_vertexbuffer = 0;
10529 rsurface.passcolor4f_bufferoffset = 0;
10530 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)
10532 f = -DotProduct(r_refdef.view.forward, n);
10534 f = f * 0.85 + 0.15; // work around so stuff won't get black
10535 f *= r_refdef.lightmapintensity;
10536 Vector4Set(c, f, f, f, 1);
10540 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10542 RSurf_DrawBatch_GL11_ApplyFakeLight();
10543 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10544 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10545 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10546 GL_Color(r, g, b, a);
10550 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10558 vec3_t ambientcolor;
10559 vec3_t diffusecolor;
10563 VectorCopy(rsurface.modellight_lightdir, lightdir);
10564 f = 0.5f * r_refdef.lightmapintensity;
10565 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10566 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10567 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10568 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10569 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10570 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10572 if (VectorLength2(diffusecolor) > 0)
10574 // q3-style directional shading
10575 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10576 rsurface.passcolor4f_vertexbuffer = 0;
10577 rsurface.passcolor4f_bufferoffset = 0;
10578 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)
10580 if ((f = DotProduct(n, lightdir)) > 0)
10581 VectorMA(ambientcolor, f, diffusecolor, c);
10583 VectorCopy(ambientcolor, c);
10590 *applycolor = false;
10594 *r = ambientcolor[0];
10595 *g = ambientcolor[1];
10596 *b = ambientcolor[2];
10597 rsurface.passcolor4f = NULL;
10598 rsurface.passcolor4f_vertexbuffer = 0;
10599 rsurface.passcolor4f_bufferoffset = 0;
10603 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10605 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10606 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10607 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10608 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10609 GL_Color(r, g, b, a);
10613 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10621 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10622 rsurface.passcolor4f_vertexbuffer = 0;
10623 rsurface.passcolor4f_bufferoffset = 0;
10625 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10627 f = 1 - RSurf_FogVertex(v);
10635 void RSurf_SetupDepthAndCulling(void)
10637 // submodels are biased to avoid z-fighting with world surfaces that they
10638 // may be exactly overlapping (avoids z-fighting artifacts on certain
10639 // doors and things in Quake maps)
10640 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10641 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10642 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10643 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10646 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10648 // transparent sky would be ridiculous
10649 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10651 R_SetupShader_Generic_NoTexture(false, false);
10652 skyrenderlater = true;
10653 RSurf_SetupDepthAndCulling();
10654 GL_DepthMask(true);
10655 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10656 // skymasking on them, and Quake3 never did sky masking (unlike
10657 // software Quake and software Quake2), so disable the sky masking
10658 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10659 // and skymasking also looks very bad when noclipping outside the
10660 // level, so don't use it then either.
10661 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10663 R_Mesh_ResetTextureState();
10664 if (skyrendermasked)
10666 R_SetupShader_DepthOrShadow(false, false, false);
10667 // depth-only (masking)
10668 GL_ColorMask(0,0,0,0);
10669 // just to make sure that braindead drivers don't draw
10670 // anything despite that colormask...
10671 GL_BlendFunc(GL_ZERO, GL_ONE);
10672 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10673 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10677 R_SetupShader_Generic_NoTexture(false, false);
10679 GL_BlendFunc(GL_ONE, GL_ZERO);
10680 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10681 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10682 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10685 if (skyrendermasked)
10686 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10688 R_Mesh_ResetTextureState();
10689 GL_Color(1, 1, 1, 1);
10692 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10693 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10694 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10696 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10700 // render screenspace normalmap to texture
10701 GL_DepthMask(true);
10702 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10707 // bind lightmap texture
10709 // water/refraction/reflection/camera surfaces have to be handled specially
10710 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10712 int start, end, startplaneindex;
10713 for (start = 0;start < texturenumsurfaces;start = end)
10715 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10716 if(startplaneindex < 0)
10718 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10719 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10723 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10725 // now that we have a batch using the same planeindex, render it
10726 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10728 // render water or distortion background
10729 GL_DepthMask(true);
10730 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);
10732 // blend surface on top
10733 GL_DepthMask(false);
10734 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10737 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10739 // render surface with reflection texture as input
10740 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10741 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);
10748 // render surface batch normally
10749 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10750 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);
10754 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10756 // OpenGL 1.3 path - anything not completely ancient
10757 qboolean applycolor;
10760 const texturelayer_t *layer;
10761 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);
10762 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10764 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10767 int layertexrgbscale;
10768 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10770 if (layerindex == 0)
10771 GL_AlphaTest(true);
10774 GL_AlphaTest(false);
10775 GL_DepthFunc(GL_EQUAL);
10778 GL_DepthMask(layer->depthmask && writedepth);
10779 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10780 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10782 layertexrgbscale = 4;
10783 VectorScale(layer->color, 0.25f, layercolor);
10785 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10787 layertexrgbscale = 2;
10788 VectorScale(layer->color, 0.5f, layercolor);
10792 layertexrgbscale = 1;
10793 VectorScale(layer->color, 1.0f, layercolor);
10795 layercolor[3] = layer->color[3];
10796 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10797 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10798 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10799 switch (layer->type)
10801 case TEXTURELAYERTYPE_LITTEXTURE:
10802 // single-pass lightmapped texture with 2x rgbscale
10803 R_Mesh_TexBind(0, r_texture_white);
10804 R_Mesh_TexMatrix(0, NULL);
10805 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10806 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10807 R_Mesh_TexBind(1, layer->texture);
10808 R_Mesh_TexMatrix(1, &layer->texmatrix);
10809 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10810 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10811 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10812 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10813 else if (FAKELIGHT_ENABLED)
10814 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10815 else if (rsurface.uselightmaptexture)
10816 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10818 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10820 case TEXTURELAYERTYPE_TEXTURE:
10821 // singletexture unlit texture with transparency support
10822 R_Mesh_TexBind(0, layer->texture);
10823 R_Mesh_TexMatrix(0, &layer->texmatrix);
10824 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10825 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10826 R_Mesh_TexBind(1, 0);
10827 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10828 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10830 case TEXTURELAYERTYPE_FOG:
10831 // singletexture fogging
10832 if (layer->texture)
10834 R_Mesh_TexBind(0, layer->texture);
10835 R_Mesh_TexMatrix(0, &layer->texmatrix);
10836 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10837 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10841 R_Mesh_TexBind(0, 0);
10842 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10844 R_Mesh_TexBind(1, 0);
10845 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10846 // generate a color array for the fog pass
10847 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10848 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10852 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10855 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10857 GL_DepthFunc(GL_LEQUAL);
10858 GL_AlphaTest(false);
10862 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10864 // OpenGL 1.1 - crusty old voodoo path
10867 const texturelayer_t *layer;
10868 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);
10869 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10871 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10873 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10875 if (layerindex == 0)
10876 GL_AlphaTest(true);
10879 GL_AlphaTest(false);
10880 GL_DepthFunc(GL_EQUAL);
10883 GL_DepthMask(layer->depthmask && writedepth);
10884 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10885 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10886 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10887 switch (layer->type)
10889 case TEXTURELAYERTYPE_LITTEXTURE:
10890 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10892 // two-pass lit texture with 2x rgbscale
10893 // first the lightmap pass
10894 R_Mesh_TexBind(0, r_texture_white);
10895 R_Mesh_TexMatrix(0, NULL);
10896 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10897 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10898 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10899 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10900 else if (FAKELIGHT_ENABLED)
10901 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10902 else if (rsurface.uselightmaptexture)
10903 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10905 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10906 // then apply the texture to it
10907 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10908 R_Mesh_TexBind(0, layer->texture);
10909 R_Mesh_TexMatrix(0, &layer->texmatrix);
10910 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10911 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10912 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);
10916 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10917 R_Mesh_TexBind(0, layer->texture);
10918 R_Mesh_TexMatrix(0, &layer->texmatrix);
10919 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10920 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10921 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10922 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);
10923 else if (FAKELIGHT_ENABLED)
10924 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);
10926 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);
10929 case TEXTURELAYERTYPE_TEXTURE:
10930 // singletexture unlit texture with transparency support
10931 R_Mesh_TexBind(0, layer->texture);
10932 R_Mesh_TexMatrix(0, &layer->texmatrix);
10933 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10934 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10935 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);
10937 case TEXTURELAYERTYPE_FOG:
10938 // singletexture fogging
10939 if (layer->texture)
10941 R_Mesh_TexBind(0, layer->texture);
10942 R_Mesh_TexMatrix(0, &layer->texmatrix);
10943 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10944 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10948 R_Mesh_TexBind(0, 0);
10949 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10951 // generate a color array for the fog pass
10952 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10953 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10957 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10960 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10962 GL_DepthFunc(GL_LEQUAL);
10963 GL_AlphaTest(false);
10967 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10971 r_vertexgeneric_t *batchvertex;
10974 // R_Mesh_ResetTextureState();
10975 R_SetupShader_Generic_NoTexture(false, false);
10977 if(rsurface.texture && rsurface.texture->currentskinframe)
10979 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10980 c[3] *= rsurface.texture->currentalpha;
10990 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10992 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10993 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10994 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10997 // brighten it up (as texture value 127 means "unlit")
10998 c[0] *= 2 * r_refdef.view.colorscale;
10999 c[1] *= 2 * r_refdef.view.colorscale;
11000 c[2] *= 2 * r_refdef.view.colorscale;
11002 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11003 c[3] *= r_wateralpha.value;
11005 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11007 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11008 GL_DepthMask(false);
11010 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11012 GL_BlendFunc(GL_ONE, GL_ONE);
11013 GL_DepthMask(false);
11015 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11017 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11018 GL_DepthMask(false);
11020 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11022 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11023 GL_DepthMask(false);
11027 GL_BlendFunc(GL_ONE, GL_ZERO);
11028 GL_DepthMask(writedepth);
11031 if (r_showsurfaces.integer == 3)
11033 rsurface.passcolor4f = NULL;
11035 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11037 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11039 rsurface.passcolor4f = NULL;
11040 rsurface.passcolor4f_vertexbuffer = 0;
11041 rsurface.passcolor4f_bufferoffset = 0;
11043 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11045 qboolean applycolor = true;
11048 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11050 r_refdef.lightmapintensity = 1;
11051 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11052 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11054 else if (FAKELIGHT_ENABLED)
11056 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11058 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11059 RSurf_DrawBatch_GL11_ApplyFakeLight();
11060 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11064 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11066 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11067 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11068 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11071 if(!rsurface.passcolor4f)
11072 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11074 RSurf_DrawBatch_GL11_ApplyAmbient();
11075 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11076 if(r_refdef.fogenabled)
11077 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11078 RSurf_DrawBatch_GL11_ClampColor();
11080 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11081 R_SetupShader_Generic_NoTexture(false, false);
11084 else if (!r_refdef.view.showdebug)
11086 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11087 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11088 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11090 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11091 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11093 R_Mesh_PrepareVertices_Generic_Unlock();
11096 else if (r_showsurfaces.integer == 4)
11098 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11099 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11100 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11102 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11103 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11104 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11106 R_Mesh_PrepareVertices_Generic_Unlock();
11109 else if (r_showsurfaces.integer == 2)
11112 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11113 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11114 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11116 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11117 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11118 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11119 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11120 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11121 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11122 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11124 R_Mesh_PrepareVertices_Generic_Unlock();
11125 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11129 int texturesurfaceindex;
11131 const msurface_t *surface;
11132 float surfacecolor4f[4];
11133 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11134 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11136 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11138 surface = texturesurfacelist[texturesurfaceindex];
11139 k = (int)(((size_t)surface) / sizeof(msurface_t));
11140 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11141 for (j = 0;j < surface->num_vertices;j++)
11143 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11144 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11148 R_Mesh_PrepareVertices_Generic_Unlock();
11153 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11156 RSurf_SetupDepthAndCulling();
11157 if (r_showsurfaces.integer)
11159 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11162 switch (vid.renderpath)
11164 case RENDERPATH_GL20:
11165 case RENDERPATH_D3D9:
11166 case RENDERPATH_D3D10:
11167 case RENDERPATH_D3D11:
11168 case RENDERPATH_SOFT:
11169 case RENDERPATH_GLES2:
11170 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11172 case RENDERPATH_GL13:
11173 case RENDERPATH_GLES1:
11174 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11176 case RENDERPATH_GL11:
11177 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11183 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11186 RSurf_SetupDepthAndCulling();
11187 if (r_showsurfaces.integer)
11189 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11192 switch (vid.renderpath)
11194 case RENDERPATH_GL20:
11195 case RENDERPATH_D3D9:
11196 case RENDERPATH_D3D10:
11197 case RENDERPATH_D3D11:
11198 case RENDERPATH_SOFT:
11199 case RENDERPATH_GLES2:
11200 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11202 case RENDERPATH_GL13:
11203 case RENDERPATH_GLES1:
11204 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11206 case RENDERPATH_GL11:
11207 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11213 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11216 int texturenumsurfaces, endsurface;
11217 texture_t *texture;
11218 const msurface_t *surface;
11219 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11221 // if the model is static it doesn't matter what value we give for
11222 // wantnormals and wanttangents, so this logic uses only rules applicable
11223 // to a model, knowing that they are meaningless otherwise
11224 if (ent == r_refdef.scene.worldentity)
11225 RSurf_ActiveWorldEntity();
11226 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11227 RSurf_ActiveModelEntity(ent, false, false, false);
11230 switch (vid.renderpath)
11232 case RENDERPATH_GL20:
11233 case RENDERPATH_D3D9:
11234 case RENDERPATH_D3D10:
11235 case RENDERPATH_D3D11:
11236 case RENDERPATH_SOFT:
11237 case RENDERPATH_GLES2:
11238 RSurf_ActiveModelEntity(ent, true, true, false);
11240 case RENDERPATH_GL11:
11241 case RENDERPATH_GL13:
11242 case RENDERPATH_GLES1:
11243 RSurf_ActiveModelEntity(ent, true, false, false);
11248 if (r_transparentdepthmasking.integer)
11250 qboolean setup = false;
11251 for (i = 0;i < numsurfaces;i = j)
11254 surface = rsurface.modelsurfaces + surfacelist[i];
11255 texture = surface->texture;
11256 rsurface.texture = R_GetCurrentTexture(texture);
11257 rsurface.lightmaptexture = NULL;
11258 rsurface.deluxemaptexture = NULL;
11259 rsurface.uselightmaptexture = false;
11260 // scan ahead until we find a different texture
11261 endsurface = min(i + 1024, numsurfaces);
11262 texturenumsurfaces = 0;
11263 texturesurfacelist[texturenumsurfaces++] = surface;
11264 for (;j < endsurface;j++)
11266 surface = rsurface.modelsurfaces + surfacelist[j];
11267 if (texture != surface->texture)
11269 texturesurfacelist[texturenumsurfaces++] = surface;
11271 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11273 // render the range of surfaces as depth
11277 GL_ColorMask(0,0,0,0);
11279 GL_DepthTest(true);
11280 GL_BlendFunc(GL_ONE, GL_ZERO);
11281 GL_DepthMask(true);
11282 // R_Mesh_ResetTextureState();
11284 RSurf_SetupDepthAndCulling();
11285 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11286 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11287 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11291 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11294 for (i = 0;i < numsurfaces;i = j)
11297 surface = rsurface.modelsurfaces + surfacelist[i];
11298 texture = surface->texture;
11299 rsurface.texture = R_GetCurrentTexture(texture);
11300 // scan ahead until we find a different texture
11301 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11302 texturenumsurfaces = 0;
11303 texturesurfacelist[texturenumsurfaces++] = surface;
11304 if(FAKELIGHT_ENABLED)
11306 rsurface.lightmaptexture = NULL;
11307 rsurface.deluxemaptexture = NULL;
11308 rsurface.uselightmaptexture = false;
11309 for (;j < endsurface;j++)
11311 surface = rsurface.modelsurfaces + surfacelist[j];
11312 if (texture != surface->texture)
11314 texturesurfacelist[texturenumsurfaces++] = surface;
11319 rsurface.lightmaptexture = surface->lightmaptexture;
11320 rsurface.deluxemaptexture = surface->deluxemaptexture;
11321 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11322 for (;j < endsurface;j++)
11324 surface = rsurface.modelsurfaces + surfacelist[j];
11325 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11327 texturesurfacelist[texturenumsurfaces++] = surface;
11330 // render the range of surfaces
11331 if (ent == r_refdef.scene.worldentity)
11332 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11334 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11336 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11339 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11341 // transparent surfaces get pushed off into the transparent queue
11342 int surfacelistindex;
11343 const msurface_t *surface;
11344 vec3_t tempcenter, center;
11345 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11347 surface = texturesurfacelist[surfacelistindex];
11348 if (r_transparent_sortsurfacesbynearest.integer)
11350 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11351 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11352 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11356 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11357 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11358 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11360 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11361 if (rsurface.entity->transparent_offset) // transparent offset
11363 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11364 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11365 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11367 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);
11371 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11373 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11375 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11377 RSurf_SetupDepthAndCulling();
11378 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11379 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11380 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11384 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11388 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11391 if (!rsurface.texture->currentnumlayers)
11393 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11394 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11396 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11398 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11399 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11400 else if (!rsurface.texture->currentnumlayers)
11402 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11404 // in the deferred case, transparent surfaces were queued during prepass
11405 if (!r_shadow_usingdeferredprepass)
11406 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11410 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11411 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11416 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11419 texture_t *texture;
11420 R_FrameData_SetMark();
11421 // break the surface list down into batches by texture and use of lightmapping
11422 for (i = 0;i < numsurfaces;i = j)
11425 // texture is the base texture pointer, rsurface.texture is the
11426 // current frame/skin the texture is directing us to use (for example
11427 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11428 // use skin 1 instead)
11429 texture = surfacelist[i]->texture;
11430 rsurface.texture = R_GetCurrentTexture(texture);
11431 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11433 // if this texture is not the kind we want, skip ahead to the next one
11434 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11438 if(FAKELIGHT_ENABLED || depthonly || prepass)
11440 rsurface.lightmaptexture = NULL;
11441 rsurface.deluxemaptexture = NULL;
11442 rsurface.uselightmaptexture = false;
11443 // simply scan ahead until we find a different texture or lightmap state
11444 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11449 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11450 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11451 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11452 // simply scan ahead until we find a different texture or lightmap state
11453 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11456 // render the range of surfaces
11457 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11459 R_FrameData_ReturnToMark();
11462 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11466 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11469 if (!rsurface.texture->currentnumlayers)
11471 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11472 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11474 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11476 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11477 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11478 else if (!rsurface.texture->currentnumlayers)
11480 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11482 // in the deferred case, transparent surfaces were queued during prepass
11483 if (!r_shadow_usingdeferredprepass)
11484 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11488 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11489 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11494 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11497 texture_t *texture;
11498 R_FrameData_SetMark();
11499 // break the surface list down into batches by texture and use of lightmapping
11500 for (i = 0;i < numsurfaces;i = j)
11503 // texture is the base texture pointer, rsurface.texture is the
11504 // current frame/skin the texture is directing us to use (for example
11505 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11506 // use skin 1 instead)
11507 texture = surfacelist[i]->texture;
11508 rsurface.texture = R_GetCurrentTexture(texture);
11509 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11511 // if this texture is not the kind we want, skip ahead to the next one
11512 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11516 if(FAKELIGHT_ENABLED || depthonly || prepass)
11518 rsurface.lightmaptexture = NULL;
11519 rsurface.deluxemaptexture = NULL;
11520 rsurface.uselightmaptexture = false;
11521 // simply scan ahead until we find a different texture or lightmap state
11522 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11527 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11528 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11529 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11530 // simply scan ahead until we find a different texture or lightmap state
11531 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11534 // render the range of surfaces
11535 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11537 R_FrameData_ReturnToMark();
11540 float locboxvertex3f[6*4*3] =
11542 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11543 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11544 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11545 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11546 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11547 1,0,0, 0,0,0, 0,1,0, 1,1,0
11550 unsigned short locboxelements[6*2*3] =
11555 12,13,14, 12,14,15,
11556 16,17,18, 16,18,19,
11560 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11563 cl_locnode_t *loc = (cl_locnode_t *)ent;
11565 float vertex3f[6*4*3];
11567 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11568 GL_DepthMask(false);
11569 GL_DepthRange(0, 1);
11570 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11571 GL_DepthTest(true);
11572 GL_CullFace(GL_NONE);
11573 R_EntityMatrix(&identitymatrix);
11575 // R_Mesh_ResetTextureState();
11577 i = surfacelist[0];
11578 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11579 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11580 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11581 surfacelist[0] < 0 ? 0.5f : 0.125f);
11583 if (VectorCompare(loc->mins, loc->maxs))
11585 VectorSet(size, 2, 2, 2);
11586 VectorMA(loc->mins, -0.5f, size, mins);
11590 VectorCopy(loc->mins, mins);
11591 VectorSubtract(loc->maxs, loc->mins, size);
11594 for (i = 0;i < 6*4*3;)
11595 for (j = 0;j < 3;j++, i++)
11596 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11598 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11599 R_SetupShader_Generic_NoTexture(false, false);
11600 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11603 void R_DrawLocs(void)
11606 cl_locnode_t *loc, *nearestloc;
11608 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11609 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11611 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11612 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11616 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11618 if (decalsystem->decals)
11619 Mem_Free(decalsystem->decals);
11620 memset(decalsystem, 0, sizeof(*decalsystem));
11623 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)
11626 tridecal_t *decals;
11629 // expand or initialize the system
11630 if (decalsystem->maxdecals <= decalsystem->numdecals)
11632 decalsystem_t old = *decalsystem;
11633 qboolean useshortelements;
11634 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11635 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11636 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)));
11637 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11638 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11639 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11640 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11641 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11642 if (decalsystem->numdecals)
11643 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11645 Mem_Free(old.decals);
11646 for (i = 0;i < decalsystem->maxdecals*3;i++)
11647 decalsystem->element3i[i] = i;
11648 if (useshortelements)
11649 for (i = 0;i < decalsystem->maxdecals*3;i++)
11650 decalsystem->element3s[i] = i;
11653 // grab a decal and search for another free slot for the next one
11654 decals = decalsystem->decals;
11655 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11656 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11658 decalsystem->freedecal = i;
11659 if (decalsystem->numdecals <= i)
11660 decalsystem->numdecals = i + 1;
11662 // initialize the decal
11664 decal->triangleindex = triangleindex;
11665 decal->surfaceindex = surfaceindex;
11666 decal->decalsequence = decalsequence;
11667 decal->color4f[0][0] = c0[0];
11668 decal->color4f[0][1] = c0[1];
11669 decal->color4f[0][2] = c0[2];
11670 decal->color4f[0][3] = 1;
11671 decal->color4f[1][0] = c1[0];
11672 decal->color4f[1][1] = c1[1];
11673 decal->color4f[1][2] = c1[2];
11674 decal->color4f[1][3] = 1;
11675 decal->color4f[2][0] = c2[0];
11676 decal->color4f[2][1] = c2[1];
11677 decal->color4f[2][2] = c2[2];
11678 decal->color4f[2][3] = 1;
11679 decal->vertex3f[0][0] = v0[0];
11680 decal->vertex3f[0][1] = v0[1];
11681 decal->vertex3f[0][2] = v0[2];
11682 decal->vertex3f[1][0] = v1[0];
11683 decal->vertex3f[1][1] = v1[1];
11684 decal->vertex3f[1][2] = v1[2];
11685 decal->vertex3f[2][0] = v2[0];
11686 decal->vertex3f[2][1] = v2[1];
11687 decal->vertex3f[2][2] = v2[2];
11688 decal->texcoord2f[0][0] = t0[0];
11689 decal->texcoord2f[0][1] = t0[1];
11690 decal->texcoord2f[1][0] = t1[0];
11691 decal->texcoord2f[1][1] = t1[1];
11692 decal->texcoord2f[2][0] = t2[0];
11693 decal->texcoord2f[2][1] = t2[1];
11694 TriangleNormal(v0, v1, v2, decal->plane);
11695 VectorNormalize(decal->plane);
11696 decal->plane[3] = DotProduct(v0, decal->plane);
11699 extern cvar_t cl_decals_bias;
11700 extern cvar_t cl_decals_models;
11701 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11702 // baseparms, parms, temps
11703 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)
11708 const float *vertex3f;
11709 const float *normal3f;
11711 float points[2][9][3];
11718 e = rsurface.modelelement3i + 3*triangleindex;
11720 vertex3f = rsurface.modelvertex3f;
11721 normal3f = rsurface.modelnormal3f;
11725 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11727 index = 3*e[cornerindex];
11728 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11733 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11735 index = 3*e[cornerindex];
11736 VectorCopy(vertex3f + index, v[cornerindex]);
11741 //TriangleNormal(v[0], v[1], v[2], normal);
11742 //if (DotProduct(normal, localnormal) < 0.0f)
11744 // clip by each of the box planes formed from the projection matrix
11745 // if anything survives, we emit the decal
11746 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]);
11749 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]);
11752 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]);
11755 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]);
11758 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]);
11761 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]);
11764 // some part of the triangle survived, so we have to accept it...
11767 // dynamic always uses the original triangle
11769 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11771 index = 3*e[cornerindex];
11772 VectorCopy(vertex3f + index, v[cornerindex]);
11775 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11777 // convert vertex positions to texcoords
11778 Matrix4x4_Transform(projection, v[cornerindex], temp);
11779 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11780 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11781 // calculate distance fade from the projection origin
11782 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11783 f = bound(0.0f, f, 1.0f);
11784 c[cornerindex][0] = r * f;
11785 c[cornerindex][1] = g * f;
11786 c[cornerindex][2] = b * f;
11787 c[cornerindex][3] = 1.0f;
11788 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11791 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);
11793 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11794 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);
11796 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)
11798 matrix4x4_t projection;
11799 decalsystem_t *decalsystem;
11802 const msurface_t *surface;
11803 const msurface_t *surfaces;
11804 const int *surfacelist;
11805 const texture_t *texture;
11807 int numsurfacelist;
11808 int surfacelistindex;
11811 float localorigin[3];
11812 float localnormal[3];
11813 float localmins[3];
11814 float localmaxs[3];
11817 float planes[6][4];
11820 int bih_triangles_count;
11821 int bih_triangles[256];
11822 int bih_surfaces[256];
11824 decalsystem = &ent->decalsystem;
11825 model = ent->model;
11826 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11828 R_DecalSystem_Reset(&ent->decalsystem);
11832 if (!model->brush.data_leafs && !cl_decals_models.integer)
11834 if (decalsystem->model)
11835 R_DecalSystem_Reset(decalsystem);
11839 if (decalsystem->model != model)
11840 R_DecalSystem_Reset(decalsystem);
11841 decalsystem->model = model;
11843 RSurf_ActiveModelEntity(ent, true, false, false);
11845 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11846 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11847 VectorNormalize(localnormal);
11848 localsize = worldsize*rsurface.inversematrixscale;
11849 localmins[0] = localorigin[0] - localsize;
11850 localmins[1] = localorigin[1] - localsize;
11851 localmins[2] = localorigin[2] - localsize;
11852 localmaxs[0] = localorigin[0] + localsize;
11853 localmaxs[1] = localorigin[1] + localsize;
11854 localmaxs[2] = localorigin[2] + localsize;
11856 //VectorCopy(localnormal, planes[4]);
11857 //VectorVectors(planes[4], planes[2], planes[0]);
11858 AnglesFromVectors(angles, localnormal, NULL, false);
11859 AngleVectors(angles, planes[0], planes[2], planes[4]);
11860 VectorNegate(planes[0], planes[1]);
11861 VectorNegate(planes[2], planes[3]);
11862 VectorNegate(planes[4], planes[5]);
11863 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11864 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11865 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11866 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11867 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11868 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11873 matrix4x4_t forwardprojection;
11874 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11875 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11880 float projectionvector[4][3];
11881 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11882 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11883 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11884 projectionvector[0][0] = planes[0][0] * ilocalsize;
11885 projectionvector[0][1] = planes[1][0] * ilocalsize;
11886 projectionvector[0][2] = planes[2][0] * ilocalsize;
11887 projectionvector[1][0] = planes[0][1] * ilocalsize;
11888 projectionvector[1][1] = planes[1][1] * ilocalsize;
11889 projectionvector[1][2] = planes[2][1] * ilocalsize;
11890 projectionvector[2][0] = planes[0][2] * ilocalsize;
11891 projectionvector[2][1] = planes[1][2] * ilocalsize;
11892 projectionvector[2][2] = planes[2][2] * ilocalsize;
11893 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11894 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11895 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11896 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11900 dynamic = model->surfmesh.isanimated;
11901 numsurfacelist = model->nummodelsurfaces;
11902 surfacelist = model->sortedmodelsurfaces;
11903 surfaces = model->data_surfaces;
11906 bih_triangles_count = -1;
11909 if(model->render_bih.numleafs)
11910 bih = &model->render_bih;
11911 else if(model->collision_bih.numleafs)
11912 bih = &model->collision_bih;
11915 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11916 if(bih_triangles_count == 0)
11918 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11920 if(bih_triangles_count > 0)
11922 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11924 surfaceindex = bih_surfaces[triangleindex];
11925 surface = surfaces + surfaceindex;
11926 texture = surface->texture;
11927 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11929 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11931 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11936 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11938 surfaceindex = surfacelist[surfacelistindex];
11939 surface = surfaces + surfaceindex;
11940 // check cull box first because it rejects more than any other check
11941 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11943 // skip transparent surfaces
11944 texture = surface->texture;
11945 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11947 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11949 numtriangles = surface->num_triangles;
11950 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11951 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11956 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11957 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)
11959 int renderentityindex;
11960 float worldmins[3];
11961 float worldmaxs[3];
11962 entity_render_t *ent;
11964 if (!cl_decals_newsystem.integer)
11967 worldmins[0] = worldorigin[0] - worldsize;
11968 worldmins[1] = worldorigin[1] - worldsize;
11969 worldmins[2] = worldorigin[2] - worldsize;
11970 worldmaxs[0] = worldorigin[0] + worldsize;
11971 worldmaxs[1] = worldorigin[1] + worldsize;
11972 worldmaxs[2] = worldorigin[2] + worldsize;
11974 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11976 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11978 ent = r_refdef.scene.entities[renderentityindex];
11979 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11982 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11986 typedef struct r_decalsystem_splatqueue_s
11988 vec3_t worldorigin;
11989 vec3_t worldnormal;
11995 r_decalsystem_splatqueue_t;
11997 int r_decalsystem_numqueued = 0;
11998 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12000 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)
12002 r_decalsystem_splatqueue_t *queue;
12004 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12007 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12008 VectorCopy(worldorigin, queue->worldorigin);
12009 VectorCopy(worldnormal, queue->worldnormal);
12010 Vector4Set(queue->color, r, g, b, a);
12011 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12012 queue->worldsize = worldsize;
12013 queue->decalsequence = cl.decalsequence++;
12016 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12019 r_decalsystem_splatqueue_t *queue;
12021 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12022 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);
12023 r_decalsystem_numqueued = 0;
12026 extern cvar_t cl_decals_max;
12027 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12030 decalsystem_t *decalsystem = &ent->decalsystem;
12037 if (!decalsystem->numdecals)
12040 if (r_showsurfaces.integer)
12043 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12045 R_DecalSystem_Reset(decalsystem);
12049 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12050 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12052 if (decalsystem->lastupdatetime)
12053 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12056 decalsystem->lastupdatetime = r_refdef.scene.time;
12057 numdecals = decalsystem->numdecals;
12059 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12061 if (decal->color4f[0][3])
12063 decal->lived += frametime;
12064 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12066 memset(decal, 0, sizeof(*decal));
12067 if (decalsystem->freedecal > i)
12068 decalsystem->freedecal = i;
12072 decal = decalsystem->decals;
12073 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12076 // collapse the array by shuffling the tail decals into the gaps
12079 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12080 decalsystem->freedecal++;
12081 if (decalsystem->freedecal == numdecals)
12083 decal[decalsystem->freedecal] = decal[--numdecals];
12086 decalsystem->numdecals = numdecals;
12088 if (numdecals <= 0)
12090 // if there are no decals left, reset decalsystem
12091 R_DecalSystem_Reset(decalsystem);
12095 extern skinframe_t *decalskinframe;
12096 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12099 decalsystem_t *decalsystem = &ent->decalsystem;
12108 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12111 numdecals = decalsystem->numdecals;
12115 if (r_showsurfaces.integer)
12118 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12120 R_DecalSystem_Reset(decalsystem);
12124 // if the model is static it doesn't matter what value we give for
12125 // wantnormals and wanttangents, so this logic uses only rules applicable
12126 // to a model, knowing that they are meaningless otherwise
12127 if (ent == r_refdef.scene.worldentity)
12128 RSurf_ActiveWorldEntity();
12130 RSurf_ActiveModelEntity(ent, false, false, false);
12132 decalsystem->lastupdatetime = r_refdef.scene.time;
12134 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12136 // update vertex positions for animated models
12137 v3f = decalsystem->vertex3f;
12138 c4f = decalsystem->color4f;
12139 t2f = decalsystem->texcoord2f;
12140 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12142 if (!decal->color4f[0][3])
12145 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12149 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12152 // update color values for fading decals
12153 if (decal->lived >= cl_decals_time.value)
12154 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12158 c4f[ 0] = decal->color4f[0][0] * alpha;
12159 c4f[ 1] = decal->color4f[0][1] * alpha;
12160 c4f[ 2] = decal->color4f[0][2] * alpha;
12162 c4f[ 4] = decal->color4f[1][0] * alpha;
12163 c4f[ 5] = decal->color4f[1][1] * alpha;
12164 c4f[ 6] = decal->color4f[1][2] * alpha;
12166 c4f[ 8] = decal->color4f[2][0] * alpha;
12167 c4f[ 9] = decal->color4f[2][1] * alpha;
12168 c4f[10] = decal->color4f[2][2] * alpha;
12171 t2f[0] = decal->texcoord2f[0][0];
12172 t2f[1] = decal->texcoord2f[0][1];
12173 t2f[2] = decal->texcoord2f[1][0];
12174 t2f[3] = decal->texcoord2f[1][1];
12175 t2f[4] = decal->texcoord2f[2][0];
12176 t2f[5] = decal->texcoord2f[2][1];
12178 // update vertex positions for animated models
12179 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12181 e = rsurface.modelelement3i + 3*decal->triangleindex;
12182 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12183 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12184 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12188 VectorCopy(decal->vertex3f[0], v3f);
12189 VectorCopy(decal->vertex3f[1], v3f + 3);
12190 VectorCopy(decal->vertex3f[2], v3f + 6);
12193 if (r_refdef.fogenabled)
12195 alpha = RSurf_FogVertex(v3f);
12196 VectorScale(c4f, alpha, c4f);
12197 alpha = RSurf_FogVertex(v3f + 3);
12198 VectorScale(c4f + 4, alpha, c4f + 4);
12199 alpha = RSurf_FogVertex(v3f + 6);
12200 VectorScale(c4f + 8, alpha, c4f + 8);
12211 r_refdef.stats[r_stat_drawndecals] += numtris;
12213 // now render the decals all at once
12214 // (this assumes they all use one particle font texture!)
12215 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);
12216 // R_Mesh_ResetTextureState();
12217 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12218 GL_DepthMask(false);
12219 GL_DepthRange(0, 1);
12220 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12221 GL_DepthTest(true);
12222 GL_CullFace(GL_NONE);
12223 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12224 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12225 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12229 static void R_DrawModelDecals(void)
12233 // fade faster when there are too many decals
12234 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12235 for (i = 0;i < r_refdef.scene.numentities;i++)
12236 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12238 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12239 for (i = 0;i < r_refdef.scene.numentities;i++)
12240 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12241 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12243 R_DecalSystem_ApplySplatEntitiesQueue();
12245 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12246 for (i = 0;i < r_refdef.scene.numentities;i++)
12247 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12249 r_refdef.stats[r_stat_totaldecals] += numdecals;
12251 if (r_showsurfaces.integer)
12254 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12256 for (i = 0;i < r_refdef.scene.numentities;i++)
12258 if (!r_refdef.viewcache.entityvisible[i])
12260 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12261 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12265 extern cvar_t mod_collision_bih;
12266 static void R_DrawDebugModel(void)
12268 entity_render_t *ent = rsurface.entity;
12269 int i, j, flagsmask;
12270 const msurface_t *surface;
12271 dp_model_t *model = ent->model;
12273 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12276 if (r_showoverdraw.value > 0)
12278 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12279 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12280 R_SetupShader_Generic_NoTexture(false, false);
12281 GL_DepthTest(false);
12282 GL_DepthMask(false);
12283 GL_DepthRange(0, 1);
12284 GL_BlendFunc(GL_ONE, GL_ONE);
12285 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12287 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12289 rsurface.texture = R_GetCurrentTexture(surface->texture);
12290 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12292 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12293 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12294 if (!rsurface.texture->currentlayers->depthmask)
12295 GL_Color(c, 0, 0, 1.0f);
12296 else if (ent == r_refdef.scene.worldentity)
12297 GL_Color(c, c, c, 1.0f);
12299 GL_Color(0, c, 0, 1.0f);
12300 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12304 rsurface.texture = NULL;
12307 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12309 // R_Mesh_ResetTextureState();
12310 R_SetupShader_Generic_NoTexture(false, false);
12311 GL_DepthRange(0, 1);
12312 GL_DepthTest(!r_showdisabledepthtest.integer);
12313 GL_DepthMask(false);
12314 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12316 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12320 qboolean cullbox = false;
12321 const q3mbrush_t *brush;
12322 const bih_t *bih = &model->collision_bih;
12323 const bih_leaf_t *bihleaf;
12324 float vertex3f[3][3];
12325 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12326 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12328 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12330 switch (bihleaf->type)
12333 brush = model->brush.data_brushes + bihleaf->itemindex;
12334 if (brush->colbrushf && brush->colbrushf->numtriangles)
12336 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);
12337 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12338 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12341 case BIH_COLLISIONTRIANGLE:
12342 triangleindex = bihleaf->itemindex;
12343 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12344 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12345 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12346 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);
12347 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12348 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12350 case BIH_RENDERTRIANGLE:
12351 triangleindex = bihleaf->itemindex;
12352 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12353 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12354 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12355 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);
12356 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12357 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12363 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12366 if (r_showtris.integer && qglPolygonMode)
12368 if (r_showdisabledepthtest.integer)
12370 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12371 GL_DepthMask(false);
12375 GL_BlendFunc(GL_ONE, GL_ZERO);
12376 GL_DepthMask(true);
12378 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12379 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12381 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12383 rsurface.texture = R_GetCurrentTexture(surface->texture);
12384 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12386 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12387 if (!rsurface.texture->currentlayers->depthmask)
12388 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12389 else if (ent == r_refdef.scene.worldentity)
12390 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12392 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12393 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12397 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12398 rsurface.texture = NULL;
12401 if (r_shownormals.value != 0 && qglBegin)
12405 if (r_showdisabledepthtest.integer)
12407 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12408 GL_DepthMask(false);
12412 GL_BlendFunc(GL_ONE, GL_ZERO);
12413 GL_DepthMask(true);
12415 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12417 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12419 rsurface.texture = R_GetCurrentTexture(surface->texture);
12420 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12422 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12423 qglBegin(GL_LINES);
12424 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12426 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12428 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12429 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12430 qglVertex3f(v[0], v[1], v[2]);
12431 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12432 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12433 qglVertex3f(v[0], v[1], v[2]);
12436 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12438 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12440 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12441 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12442 qglVertex3f(v[0], v[1], v[2]);
12443 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12444 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12445 qglVertex3f(v[0], v[1], v[2]);
12448 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12450 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12452 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12453 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12454 qglVertex3f(v[0], v[1], v[2]);
12455 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12456 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12457 qglVertex3f(v[0], v[1], v[2]);
12460 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12462 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12464 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12465 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12466 qglVertex3f(v[0], v[1], v[2]);
12467 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12468 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12469 qglVertex3f(v[0], v[1], v[2]);
12476 rsurface.texture = NULL;
12481 int r_maxsurfacelist = 0;
12482 const msurface_t **r_surfacelist = NULL;
12483 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12485 int i, j, endj, flagsmask;
12486 dp_model_t *model = r_refdef.scene.worldmodel;
12487 msurface_t *surfaces;
12488 unsigned char *update;
12489 int numsurfacelist = 0;
12493 if (r_maxsurfacelist < model->num_surfaces)
12495 r_maxsurfacelist = model->num_surfaces;
12497 Mem_Free((msurface_t**)r_surfacelist);
12498 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12501 RSurf_ActiveWorldEntity();
12503 surfaces = model->data_surfaces;
12504 update = model->brushq1.lightmapupdateflags;
12506 // update light styles on this submodel
12507 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12509 model_brush_lightstyleinfo_t *style;
12510 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12512 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12514 int *list = style->surfacelist;
12515 style->value = r_refdef.scene.lightstylevalue[style->style];
12516 for (j = 0;j < style->numsurfaces;j++)
12517 update[list[j]] = true;
12522 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12526 R_DrawDebugModel();
12527 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12531 rsurface.lightmaptexture = NULL;
12532 rsurface.deluxemaptexture = NULL;
12533 rsurface.uselightmaptexture = false;
12534 rsurface.texture = NULL;
12535 rsurface.rtlight = NULL;
12536 numsurfacelist = 0;
12537 // add visible surfaces to draw list
12538 for (i = 0;i < model->nummodelsurfaces;i++)
12540 j = model->sortedmodelsurfaces[i];
12541 if (r_refdef.viewcache.world_surfacevisible[j])
12542 r_surfacelist[numsurfacelist++] = surfaces + j;
12544 // update lightmaps if needed
12545 if (model->brushq1.firstrender)
12547 model->brushq1.firstrender = false;
12548 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12550 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12554 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12555 if (r_refdef.viewcache.world_surfacevisible[j])
12557 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12559 // don't do anything if there were no surfaces
12560 if (!numsurfacelist)
12562 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12565 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12567 // add to stats if desired
12568 if (r_speeds.integer && !skysurfaces && !depthonly)
12570 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12571 for (j = 0;j < numsurfacelist;j++)
12572 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12575 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12578 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12580 int i, j, endj, flagsmask;
12581 dp_model_t *model = ent->model;
12582 msurface_t *surfaces;
12583 unsigned char *update;
12584 int numsurfacelist = 0;
12588 if (r_maxsurfacelist < model->num_surfaces)
12590 r_maxsurfacelist = model->num_surfaces;
12592 Mem_Free((msurface_t **)r_surfacelist);
12593 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12596 // if the model is static it doesn't matter what value we give for
12597 // wantnormals and wanttangents, so this logic uses only rules applicable
12598 // to a model, knowing that they are meaningless otherwise
12599 if (ent == r_refdef.scene.worldentity)
12600 RSurf_ActiveWorldEntity();
12601 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12602 RSurf_ActiveModelEntity(ent, false, false, false);
12604 RSurf_ActiveModelEntity(ent, true, true, true);
12605 else if (depthonly)
12607 switch (vid.renderpath)
12609 case RENDERPATH_GL20:
12610 case RENDERPATH_D3D9:
12611 case RENDERPATH_D3D10:
12612 case RENDERPATH_D3D11:
12613 case RENDERPATH_SOFT:
12614 case RENDERPATH_GLES2:
12615 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12617 case RENDERPATH_GL11:
12618 case RENDERPATH_GL13:
12619 case RENDERPATH_GLES1:
12620 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12626 switch (vid.renderpath)
12628 case RENDERPATH_GL20:
12629 case RENDERPATH_D3D9:
12630 case RENDERPATH_D3D10:
12631 case RENDERPATH_D3D11:
12632 case RENDERPATH_SOFT:
12633 case RENDERPATH_GLES2:
12634 RSurf_ActiveModelEntity(ent, true, true, false);
12636 case RENDERPATH_GL11:
12637 case RENDERPATH_GL13:
12638 case RENDERPATH_GLES1:
12639 RSurf_ActiveModelEntity(ent, true, false, false);
12644 surfaces = model->data_surfaces;
12645 update = model->brushq1.lightmapupdateflags;
12647 // update light styles
12648 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12650 model_brush_lightstyleinfo_t *style;
12651 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12653 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12655 int *list = style->surfacelist;
12656 style->value = r_refdef.scene.lightstylevalue[style->style];
12657 for (j = 0;j < style->numsurfaces;j++)
12658 update[list[j]] = true;
12663 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12667 R_DrawDebugModel();
12668 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12672 rsurface.lightmaptexture = NULL;
12673 rsurface.deluxemaptexture = NULL;
12674 rsurface.uselightmaptexture = false;
12675 rsurface.texture = NULL;
12676 rsurface.rtlight = NULL;
12677 numsurfacelist = 0;
12678 // add visible surfaces to draw list
12679 for (i = 0;i < model->nummodelsurfaces;i++)
12680 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12681 // don't do anything if there were no surfaces
12682 if (!numsurfacelist)
12684 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12687 // update lightmaps if needed
12691 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12696 R_BuildLightMap(ent, surfaces + j);
12701 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12703 // add to stats if desired
12704 if (r_speeds.integer && !skysurfaces && !depthonly)
12706 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12707 for (j = 0;j < numsurfacelist;j++)
12708 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12711 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12714 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12716 static texture_t texture;
12717 static msurface_t surface;
12718 const msurface_t *surfacelist = &surface;
12720 // fake enough texture and surface state to render this geometry
12722 texture.update_lastrenderframe = -1; // regenerate this texture
12723 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12724 texture.currentskinframe = skinframe;
12725 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12726 texture.offsetmapping = OFFSETMAPPING_OFF;
12727 texture.offsetscale = 1;
12728 texture.specularscalemod = 1;
12729 texture.specularpowermod = 1;
12730 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12731 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12732 // JUST GREP FOR "specularscalemod = 1".
12734 surface.texture = &texture;
12735 surface.num_triangles = numtriangles;
12736 surface.num_firsttriangle = firsttriangle;
12737 surface.num_vertices = numvertices;
12738 surface.num_firstvertex = firstvertex;
12741 rsurface.texture = R_GetCurrentTexture(surface.texture);
12742 rsurface.lightmaptexture = NULL;
12743 rsurface.deluxemaptexture = NULL;
12744 rsurface.uselightmaptexture = false;
12745 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12748 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)
12750 static msurface_t surface;
12751 const msurface_t *surfacelist = &surface;
12753 // fake enough texture and surface state to render this geometry
12754 surface.texture = texture;
12755 surface.num_triangles = numtriangles;
12756 surface.num_firsttriangle = firsttriangle;
12757 surface.num_vertices = numvertices;
12758 surface.num_firstvertex = firstvertex;
12761 rsurface.texture = R_GetCurrentTexture(surface.texture);
12762 rsurface.lightmaptexture = NULL;
12763 rsurface.deluxemaptexture = NULL;
12764 rsurface.uselightmaptexture = false;
12765 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);