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;
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
65 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!"};
66 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!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 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)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 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"};
72 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"};
73 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"};
74 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"};
75 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"};
76 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"};
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 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"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
81 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)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
84 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"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
96 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)"};
97 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
98 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
99 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"};
100 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"};
101 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
102 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"};
103 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"};
104 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"};
105 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
106 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
107 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
108 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
109 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
110 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
111 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
112 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)"};
113 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)"};
114 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
115 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
116 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
117 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
118 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
120 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
121 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
122 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
124 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
125 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
126 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
127 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."};
128 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
129 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
130 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
131 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."};
132 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
133 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
134 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
135 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."};
136 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
137 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"};
138 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"};
139 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
140 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
141 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
142 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
143 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
144 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"};
145 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
146 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
147 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
148 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
149 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
151 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
152 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
153 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
154 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
155 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
156 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
157 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
158 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
160 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)"};
161 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"};
163 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
164 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
165 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
167 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"};
168 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"};
169 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"};
170 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
171 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
172 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"};
173 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)"};
174 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)"};
175 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
177 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
178 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)"};
179 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
180 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)"};
181 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
182 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)"};
183 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)"};
184 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
185 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"};
186 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."};
187 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
188 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)"};
189 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)"};
190 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)"};
191 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)"};
192 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)"};
193 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)"};
194 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)"};
195 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)"};
197 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)"};
198 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
199 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
200 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"};
201 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
202 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
203 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
204 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"};
205 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"};
206 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)"};
208 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
209 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
210 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
211 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
213 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
214 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
216 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
217 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
218 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
219 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
220 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
221 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
223 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
224 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
225 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
226 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
227 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
228 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
229 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
230 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
231 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
232 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
234 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"};
236 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"};
238 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
240 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
242 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)"};
243 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)"};
244 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
245 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
247 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
248 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"};
250 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."};
252 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)"};
253 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
255 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
256 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
257 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
258 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
261 extern cvar_t v_glslgamma;
262 extern cvar_t v_glslgamma_2d;
264 extern qboolean v_flipped_state;
266 r_framebufferstate_t r_fb;
268 /// shadow volume bsp struct with automatically growing nodes buffer
271 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
273 rtexture_t *r_texture_blanknormalmap;
274 rtexture_t *r_texture_white;
275 rtexture_t *r_texture_grey128;
276 rtexture_t *r_texture_black;
277 rtexture_t *r_texture_notexture;
278 rtexture_t *r_texture_whitecube;
279 rtexture_t *r_texture_normalizationcube;
280 rtexture_t *r_texture_fogattenuation;
281 rtexture_t *r_texture_fogheighttexture;
282 rtexture_t *r_texture_gammaramps;
283 unsigned int r_texture_gammaramps_serial;
284 //rtexture_t *r_texture_fogintensity;
285 rtexture_t *r_texture_reflectcube;
287 // TODO: hash lookups?
288 typedef struct cubemapinfo_s
295 int r_texture_numcubemaps;
296 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
298 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
299 unsigned int r_numqueries;
300 unsigned int r_maxqueries;
302 typedef struct r_qwskincache_s
304 char name[MAX_QPATH];
305 skinframe_t *skinframe;
309 static r_qwskincache_t *r_qwskincache;
310 static int r_qwskincache_size;
312 /// vertex coordinates for a quad that covers the screen exactly
313 extern const float r_screenvertex3f[12];
314 extern const float r_d3dscreenvertex3f[12];
315 const float r_screenvertex3f[12] =
322 const float r_d3dscreenvertex3f[12] =
330 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
333 for (i = 0;i < verts;i++)
344 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
347 for (i = 0;i < verts;i++)
357 // FIXME: move this to client?
360 if (gamemode == GAME_NEHAHRA)
362 Cvar_Set("gl_fogenable", "0");
363 Cvar_Set("gl_fogdensity", "0.2");
364 Cvar_Set("gl_fogred", "0.3");
365 Cvar_Set("gl_foggreen", "0.3");
366 Cvar_Set("gl_fogblue", "0.3");
368 r_refdef.fog_density = 0;
369 r_refdef.fog_red = 0;
370 r_refdef.fog_green = 0;
371 r_refdef.fog_blue = 0;
372 r_refdef.fog_alpha = 1;
373 r_refdef.fog_start = 0;
374 r_refdef.fog_end = 16384;
375 r_refdef.fog_height = 1<<30;
376 r_refdef.fog_fadedepth = 128;
377 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
380 static void R_BuildBlankTextures(void)
382 unsigned char data[4];
383 data[2] = 128; // normal X
384 data[1] = 128; // normal Y
385 data[0] = 255; // normal Z
386 data[3] = 255; // height
387 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
402 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
405 static void R_BuildNoTexture(void)
408 unsigned char pix[16][16][4];
409 // this makes a light grey/dark grey checkerboard texture
410 for (y = 0;y < 16;y++)
412 for (x = 0;x < 16;x++)
414 if ((y < 8) ^ (x < 8))
430 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
433 static void R_BuildWhiteCube(void)
435 unsigned char data[6*1*1*4];
436 memset(data, 255, sizeof(data));
437 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
440 static void R_BuildNormalizationCube(void)
444 vec_t s, t, intensity;
447 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
448 for (side = 0;side < 6;side++)
450 for (y = 0;y < NORMSIZE;y++)
452 for (x = 0;x < NORMSIZE;x++)
454 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
455 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
490 intensity = 127.0f / sqrt(DotProduct(v, v));
491 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
492 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
493 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
494 data[((side*64+y)*64+x)*4+3] = 255;
498 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
502 static void R_BuildFogTexture(void)
506 unsigned char data1[FOGWIDTH][4];
507 //unsigned char data2[FOGWIDTH][4];
510 r_refdef.fogmasktable_start = r_refdef.fog_start;
511 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
512 r_refdef.fogmasktable_range = r_refdef.fogrange;
513 r_refdef.fogmasktable_density = r_refdef.fog_density;
515 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
516 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
518 d = (x * r - r_refdef.fogmasktable_start);
519 if(developer_extra.integer)
520 Con_DPrintf("%f ", d);
522 if (r_fog_exp2.integer)
523 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
525 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
526 if(developer_extra.integer)
527 Con_DPrintf(" : %f ", alpha);
528 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
529 if(developer_extra.integer)
530 Con_DPrintf(" = %f\n", alpha);
531 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
534 for (x = 0;x < FOGWIDTH;x++)
536 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
541 //data2[x][0] = 255 - b;
542 //data2[x][1] = 255 - b;
543 //data2[x][2] = 255 - b;
546 if (r_texture_fogattenuation)
548 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
549 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
553 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
554 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
558 static void R_BuildFogHeightTexture(void)
560 unsigned char *inpixels;
568 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
569 if (r_refdef.fogheighttexturename[0])
570 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
573 r_refdef.fog_height_tablesize = 0;
574 if (r_texture_fogheighttexture)
575 R_FreeTexture(r_texture_fogheighttexture);
576 r_texture_fogheighttexture = NULL;
577 if (r_refdef.fog_height_table2d)
578 Mem_Free(r_refdef.fog_height_table2d);
579 r_refdef.fog_height_table2d = NULL;
580 if (r_refdef.fog_height_table1d)
581 Mem_Free(r_refdef.fog_height_table1d);
582 r_refdef.fog_height_table1d = NULL;
586 r_refdef.fog_height_tablesize = size;
587 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
588 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
589 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
591 // LordHavoc: now the magic - what is that table2d for? it is a cooked
592 // average fog color table accounting for every fog layer between a point
593 // and the camera. (Note: attenuation is handled separately!)
594 for (y = 0;y < size;y++)
596 for (x = 0;x < size;x++)
602 for (j = x;j <= y;j++)
604 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
610 for (j = x;j >= y;j--)
612 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
617 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
618 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
619 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
620 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
623 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
626 //=======================================================================================================================================================
628 static const char *builtinshaderstrings[] =
630 #include "shader_glsl.h"
634 const char *builtinhlslshaderstrings[] =
636 #include "shader_hlsl.h"
640 char *glslshaderstring = NULL;
641 char *hlslshaderstring = NULL;
643 //=======================================================================================================================================================
645 typedef struct shaderpermutationinfo_s
650 shaderpermutationinfo_t;
652 typedef struct shadermodeinfo_s
654 const char *filename;
660 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
661 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
663 {"#define USEDIFFUSE\n", " diffuse"},
664 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
665 {"#define USEVIEWTINT\n", " viewtint"},
666 {"#define USECOLORMAPPING\n", " colormapping"},
667 {"#define USESATURATION\n", " saturation"},
668 {"#define USEFOGINSIDE\n", " foginside"},
669 {"#define USEFOGOUTSIDE\n", " fogoutside"},
670 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
671 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
672 {"#define USEGAMMARAMPS\n", " gammaramps"},
673 {"#define USECUBEFILTER\n", " cubefilter"},
674 {"#define USEGLOW\n", " glow"},
675 {"#define USEBLOOM\n", " bloom"},
676 {"#define USESPECULAR\n", " specular"},
677 {"#define USEPOSTPROCESSING\n", " postprocessing"},
678 {"#define USEREFLECTION\n", " reflection"},
679 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
680 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
681 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
682 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
683 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
684 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
685 {"#define USEALPHAKILL\n", " alphakill"},
686 {"#define USEREFLECTCUBE\n", " reflectcube"},
687 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
688 {"#define USEBOUNCEGRID\n", " bouncegrid"},
689 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
690 {"#define USETRIPPY\n", " trippy"},
691 {"#define USEDEPTHRGB\n", " depthrgb"},
692 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
693 {"#define USESKELETAL\n", " skeletal"},
694 {"#define USEOCCLUDE\n", " occlude"}
697 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
698 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
700 {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
701 {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
702 {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
703 {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
704 {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
705 {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
706 {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
707 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
708 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
709 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
710 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
711 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
712 {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
713 {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
714 {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
715 {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
716 {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
719 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
721 {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
722 {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
723 {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
724 {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
725 {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
726 {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
727 {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
728 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
729 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
730 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
731 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
732 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
733 {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
734 {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
735 {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
736 {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
737 {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
740 struct r_glsl_permutation_s;
741 typedef struct r_glsl_permutation_s
744 struct r_glsl_permutation_s *hashnext;
746 unsigned int permutation;
748 /// indicates if we have tried compiling this permutation already
750 /// 0 if compilation failed
752 // texture units assigned to each detected uniform
753 int tex_Texture_First;
754 int tex_Texture_Second;
755 int tex_Texture_GammaRamps;
756 int tex_Texture_Normal;
757 int tex_Texture_Color;
758 int tex_Texture_Gloss;
759 int tex_Texture_Glow;
760 int tex_Texture_SecondaryNormal;
761 int tex_Texture_SecondaryColor;
762 int tex_Texture_SecondaryGloss;
763 int tex_Texture_SecondaryGlow;
764 int tex_Texture_Pants;
765 int tex_Texture_Shirt;
766 int tex_Texture_FogHeightTexture;
767 int tex_Texture_FogMask;
768 int tex_Texture_Lightmap;
769 int tex_Texture_Deluxemap;
770 int tex_Texture_Attenuation;
771 int tex_Texture_Cube;
772 int tex_Texture_Refraction;
773 int tex_Texture_Reflection;
774 int tex_Texture_ShadowMap2D;
775 int tex_Texture_CubeProjection;
776 int tex_Texture_ScreenNormalMap;
777 int tex_Texture_ScreenDiffuse;
778 int tex_Texture_ScreenSpecular;
779 int tex_Texture_ReflectMask;
780 int tex_Texture_ReflectCube;
781 int tex_Texture_BounceGrid;
782 /// locations of detected uniforms in program object, or -1 if not found
783 int loc_Texture_First;
784 int loc_Texture_Second;
785 int loc_Texture_GammaRamps;
786 int loc_Texture_Normal;
787 int loc_Texture_Color;
788 int loc_Texture_Gloss;
789 int loc_Texture_Glow;
790 int loc_Texture_SecondaryNormal;
791 int loc_Texture_SecondaryColor;
792 int loc_Texture_SecondaryGloss;
793 int loc_Texture_SecondaryGlow;
794 int loc_Texture_Pants;
795 int loc_Texture_Shirt;
796 int loc_Texture_FogHeightTexture;
797 int loc_Texture_FogMask;
798 int loc_Texture_Lightmap;
799 int loc_Texture_Deluxemap;
800 int loc_Texture_Attenuation;
801 int loc_Texture_Cube;
802 int loc_Texture_Refraction;
803 int loc_Texture_Reflection;
804 int loc_Texture_ShadowMap2D;
805 int loc_Texture_CubeProjection;
806 int loc_Texture_ScreenNormalMap;
807 int loc_Texture_ScreenDiffuse;
808 int loc_Texture_ScreenSpecular;
809 int loc_Texture_ReflectMask;
810 int loc_Texture_ReflectCube;
811 int loc_Texture_BounceGrid;
813 int loc_BloomBlur_Parameters;
815 int loc_Color_Ambient;
816 int loc_Color_Diffuse;
817 int loc_Color_Specular;
821 int loc_DeferredColor_Ambient;
822 int loc_DeferredColor_Diffuse;
823 int loc_DeferredColor_Specular;
824 int loc_DeferredMod_Diffuse;
825 int loc_DeferredMod_Specular;
826 int loc_DistortScaleRefractReflect;
829 int loc_FogHeightFade;
831 int loc_FogPlaneViewDist;
832 int loc_FogRangeRecip;
835 int loc_LightPosition;
836 int loc_OffsetMapping_ScaleSteps;
837 int loc_OffsetMapping_LodDistance;
838 int loc_OffsetMapping_Bias;
840 int loc_ReflectColor;
841 int loc_ReflectFactor;
842 int loc_ReflectOffset;
843 int loc_RefractColor;
845 int loc_ScreenCenterRefractReflect;
846 int loc_ScreenScaleRefractReflect;
847 int loc_ScreenToDepth;
848 int loc_ShadowMap_Parameters;
849 int loc_ShadowMap_TextureScale;
850 int loc_SpecularPower;
851 int loc_Skeletal_Transform12;
856 int loc_ViewTintColor;
858 int loc_ModelToLight;
860 int loc_BackgroundTexMatrix;
861 int loc_ModelViewProjectionMatrix;
862 int loc_ModelViewMatrix;
863 int loc_PixelToScreenTexCoord;
864 int loc_ModelToReflectCube;
865 int loc_ShadowMapMatrix;
866 int loc_BloomColorSubtract;
867 int loc_NormalmapScrollBlend;
868 int loc_BounceGridMatrix;
869 int loc_BounceGridIntensity;
870 /// uniform block bindings
871 int ubibind_Skeletal_Transform12_UniformBlock;
872 /// uniform block indices
873 int ubiloc_Skeletal_Transform12_UniformBlock;
875 r_glsl_permutation_t;
877 #define SHADERPERMUTATION_HASHSIZE 256
880 // non-degradable "lightweight" shader parameters to keep the permutations simpler
881 // these can NOT degrade! only use for simple stuff
884 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
885 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
886 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
887 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
888 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
889 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
890 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
891 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
892 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
893 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
894 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
895 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
896 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
897 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
899 #define SHADERSTATICPARMS_COUNT 14
901 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
902 static int shaderstaticparms_count = 0;
904 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
905 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
907 extern qboolean r_shadow_shadowmapsampler;
908 extern int r_shadow_shadowmappcf;
909 qboolean R_CompileShader_CheckStaticParms(void)
911 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
912 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
913 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
916 if (r_glsl_saturation_redcompensate.integer)
917 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
918 if (r_glsl_vertextextureblend_usebothalphas.integer)
919 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
920 if (r_shadow_glossexact.integer)
921 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
922 if (r_glsl_postprocess.integer)
924 if (r_glsl_postprocess_uservec1_enable.integer)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
926 if (r_glsl_postprocess_uservec2_enable.integer)
927 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
928 if (r_glsl_postprocess_uservec3_enable.integer)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
930 if (r_glsl_postprocess_uservec4_enable.integer)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
934 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
935 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
936 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
938 if (r_shadow_shadowmapsampler)
939 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
940 if (r_shadow_shadowmappcf > 1)
941 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
942 else if (r_shadow_shadowmappcf)
943 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
944 if (r_celshading.integer)
945 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
946 if (r_celoutlines.integer)
947 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
949 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
952 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
953 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
954 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
956 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
957 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
959 shaderstaticparms_count = 0;
962 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
963 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
964 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
965 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
966 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
967 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
968 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
969 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
970 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
971 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
972 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
973 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
974 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
975 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
978 /// information about each possible shader permutation
979 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
980 /// currently selected permutation
981 r_glsl_permutation_t *r_glsl_permutation;
982 /// storage for permutations linked in the hash table
983 memexpandablearray_t r_glsl_permutationarray;
985 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
987 //unsigned int hashdepth = 0;
988 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
989 r_glsl_permutation_t *p;
990 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
992 if (p->mode == mode && p->permutation == permutation)
994 //if (hashdepth > 10)
995 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1000 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1002 p->permutation = permutation;
1003 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1004 r_glsl_permutationhash[mode][hashindex] = p;
1005 //if (hashdepth > 10)
1006 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1010 static char *R_ShaderStrCat(const char **strings)
1013 const char **p = strings;
1016 for (p = strings;(t = *p);p++)
1019 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1021 for (p = strings;(t = *p);p++)
1031 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1034 if (!filename || !filename[0])
1036 // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1037 if (!strcmp(filename, "glsl/default.glsl"))
1040 return R_ShaderStrCat(builtinshaderstrings);
1041 if (!glslshaderstring)
1043 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1044 if (glslshaderstring)
1045 Con_DPrintf("Loading shaders from file %s...\n", filename);
1047 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1049 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1050 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1051 return shaderstring;
1053 if (!strcmp(filename, "hlsl/default.hlsl"))
1056 return R_ShaderStrCat(builtinhlslshaderstrings);
1057 if (!hlslshaderstring)
1059 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1060 if (hlslshaderstring)
1061 Con_DPrintf("Loading shaders from file %s...\n", filename);
1063 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1065 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1066 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1067 return shaderstring;
1069 // we don't have builtin strings for any other files
1072 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1075 if (printfromdisknotice)
1076 Con_DPrintf("from disk %s... ", filename);
1077 return shaderstring;
1079 return shaderstring;
1082 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1087 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1089 char permutationname[256];
1090 int vertstrings_count = 0;
1091 int geomstrings_count = 0;
1092 int fragstrings_count = 0;
1093 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1102 permutationname[0] = 0;
1103 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1105 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1107 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1108 if(vid.support.glshaderversion >= 140)
1110 vertstrings_list[vertstrings_count++] = "#version 140\n";
1111 geomstrings_list[geomstrings_count++] = "#version 140\n";
1112 fragstrings_list[fragstrings_count++] = "#version 140\n";
1113 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1114 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1115 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1117 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1118 else if(vid.support.glshaderversion >= 130)
1120 vertstrings_list[vertstrings_count++] = "#version 130\n";
1121 geomstrings_list[geomstrings_count++] = "#version 130\n";
1122 fragstrings_list[fragstrings_count++] = "#version 130\n";
1123 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1124 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1125 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1128 // the first pretext is which type of shader to compile as
1129 // (later these will all be bound together as a program object)
1130 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1131 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1132 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1134 // the second pretext is the mode (for example a light source)
1135 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1136 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1137 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1138 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1140 // now add all the permutation pretexts
1141 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1143 if (permutation & (1<<i))
1145 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1146 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1147 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1148 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1152 // keep line numbers correct
1153 vertstrings_list[vertstrings_count++] = "\n";
1154 geomstrings_list[geomstrings_count++] = "\n";
1155 fragstrings_list[fragstrings_count++] = "\n";
1160 R_CompileShader_AddStaticParms(mode, permutation);
1161 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1162 vertstrings_count += shaderstaticparms_count;
1163 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1164 geomstrings_count += shaderstaticparms_count;
1165 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1166 fragstrings_count += shaderstaticparms_count;
1168 // now append the shader text itself
1169 vertstrings_list[vertstrings_count++] = sourcestring;
1170 geomstrings_list[geomstrings_count++] = sourcestring;
1171 fragstrings_list[fragstrings_count++] = sourcestring;
1173 // compile the shader program
1174 if (vertstrings_count + geomstrings_count + fragstrings_count)
1175 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1179 qglUseProgram(p->program);CHECKGLERROR
1180 // look up all the uniform variable names we care about, so we don't
1181 // have to look them up every time we set them
1186 GLint activeuniformindex = 0;
1187 GLint numactiveuniforms = 0;
1188 char uniformname[128];
1189 GLsizei uniformnamelength = 0;
1190 GLint uniformsize = 0;
1191 GLenum uniformtype = 0;
1192 memset(uniformname, 0, sizeof(uniformname));
1193 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1194 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1195 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1197 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1198 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1203 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1204 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1205 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1206 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1207 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1208 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1209 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1210 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1211 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1212 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1213 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1214 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1215 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1216 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1217 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1218 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1219 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1220 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1221 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1222 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1223 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1224 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1225 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1226 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1227 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1228 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1229 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1230 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1231 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1232 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1233 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1234 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1235 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1236 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1237 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1238 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1239 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1240 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1241 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1242 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1243 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1244 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1245 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1246 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1247 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1248 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1249 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1250 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1251 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1252 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1253 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1254 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1255 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1256 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1257 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1258 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1259 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1260 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1261 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1262 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1263 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1264 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1265 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1266 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1267 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1268 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1269 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1270 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1271 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1272 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1273 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1274 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1275 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1276 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1277 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1278 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1279 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1280 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1281 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1282 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1283 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1284 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1285 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1286 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1287 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1288 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1289 // initialize the samplers to refer to the texture units we use
1290 p->tex_Texture_First = -1;
1291 p->tex_Texture_Second = -1;
1292 p->tex_Texture_GammaRamps = -1;
1293 p->tex_Texture_Normal = -1;
1294 p->tex_Texture_Color = -1;
1295 p->tex_Texture_Gloss = -1;
1296 p->tex_Texture_Glow = -1;
1297 p->tex_Texture_SecondaryNormal = -1;
1298 p->tex_Texture_SecondaryColor = -1;
1299 p->tex_Texture_SecondaryGloss = -1;
1300 p->tex_Texture_SecondaryGlow = -1;
1301 p->tex_Texture_Pants = -1;
1302 p->tex_Texture_Shirt = -1;
1303 p->tex_Texture_FogHeightTexture = -1;
1304 p->tex_Texture_FogMask = -1;
1305 p->tex_Texture_Lightmap = -1;
1306 p->tex_Texture_Deluxemap = -1;
1307 p->tex_Texture_Attenuation = -1;
1308 p->tex_Texture_Cube = -1;
1309 p->tex_Texture_Refraction = -1;
1310 p->tex_Texture_Reflection = -1;
1311 p->tex_Texture_ShadowMap2D = -1;
1312 p->tex_Texture_CubeProjection = -1;
1313 p->tex_Texture_ScreenNormalMap = -1;
1314 p->tex_Texture_ScreenDiffuse = -1;
1315 p->tex_Texture_ScreenSpecular = -1;
1316 p->tex_Texture_ReflectMask = -1;
1317 p->tex_Texture_ReflectCube = -1;
1318 p->tex_Texture_BounceGrid = -1;
1319 // bind the texture samplers in use
1321 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1322 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1323 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1324 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1325 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1326 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1327 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1328 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1329 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1330 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1331 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1332 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1333 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1334 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1335 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1336 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1337 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1338 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1339 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1340 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1341 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1342 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1343 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1344 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1345 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1346 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1347 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1348 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1349 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1350 // get the uniform block indices so we can bind them
1351 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1352 if (vid.support.arb_uniform_buffer_object)
1353 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1356 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1357 // clear the uniform block bindings
1358 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1359 // bind the uniform blocks in use
1361 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1362 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1364 // we're done compiling and setting up the shader, at least until it is used
1366 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1369 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1373 Mem_Free(sourcestring);
1376 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1378 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1379 if (r_glsl_permutation != perm)
1381 r_glsl_permutation = perm;
1382 if (!r_glsl_permutation->program)
1384 if (!r_glsl_permutation->compiled)
1386 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1387 R_GLSL_CompilePermutation(perm, mode, permutation);
1389 if (!r_glsl_permutation->program)
1391 // remove features until we find a valid permutation
1393 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1395 // reduce i more quickly whenever it would not remove any bits
1396 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1397 if (!(permutation & j))
1400 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1401 if (!r_glsl_permutation->compiled)
1402 R_GLSL_CompilePermutation(perm, mode, permutation);
1403 if (r_glsl_permutation->program)
1406 if (i >= SHADERPERMUTATION_COUNT)
1408 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1409 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1410 qglUseProgram(0);CHECKGLERROR
1411 return; // no bit left to clear, entire mode is broken
1416 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1418 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1419 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1420 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1428 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1429 extern D3DCAPS9 vid_d3d9caps;
1432 struct r_hlsl_permutation_s;
1433 typedef struct r_hlsl_permutation_s
1435 /// hash lookup data
1436 struct r_hlsl_permutation_s *hashnext;
1438 unsigned int permutation;
1440 /// indicates if we have tried compiling this permutation already
1442 /// NULL if compilation failed
1443 IDirect3DVertexShader9 *vertexshader;
1444 IDirect3DPixelShader9 *pixelshader;
1446 r_hlsl_permutation_t;
1448 typedef enum D3DVSREGISTER_e
1450 D3DVSREGISTER_TexMatrix = 0, // float4x4
1451 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1452 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1453 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1454 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1455 D3DVSREGISTER_ModelToLight = 20, // float4x4
1456 D3DVSREGISTER_EyePosition = 24,
1457 D3DVSREGISTER_FogPlane = 25,
1458 D3DVSREGISTER_LightDir = 26,
1459 D3DVSREGISTER_LightPosition = 27,
1463 typedef enum D3DPSREGISTER_e
1465 D3DPSREGISTER_Alpha = 0,
1466 D3DPSREGISTER_BloomBlur_Parameters = 1,
1467 D3DPSREGISTER_ClientTime = 2,
1468 D3DPSREGISTER_Color_Ambient = 3,
1469 D3DPSREGISTER_Color_Diffuse = 4,
1470 D3DPSREGISTER_Color_Specular = 5,
1471 D3DPSREGISTER_Color_Glow = 6,
1472 D3DPSREGISTER_Color_Pants = 7,
1473 D3DPSREGISTER_Color_Shirt = 8,
1474 D3DPSREGISTER_DeferredColor_Ambient = 9,
1475 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1476 D3DPSREGISTER_DeferredColor_Specular = 11,
1477 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1478 D3DPSREGISTER_DeferredMod_Specular = 13,
1479 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1480 D3DPSREGISTER_EyePosition = 15, // unused
1481 D3DPSREGISTER_FogColor = 16,
1482 D3DPSREGISTER_FogHeightFade = 17,
1483 D3DPSREGISTER_FogPlane = 18,
1484 D3DPSREGISTER_FogPlaneViewDist = 19,
1485 D3DPSREGISTER_FogRangeRecip = 20,
1486 D3DPSREGISTER_LightColor = 21,
1487 D3DPSREGISTER_LightDir = 22, // unused
1488 D3DPSREGISTER_LightPosition = 23,
1489 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1490 D3DPSREGISTER_PixelSize = 25,
1491 D3DPSREGISTER_ReflectColor = 26,
1492 D3DPSREGISTER_ReflectFactor = 27,
1493 D3DPSREGISTER_ReflectOffset = 28,
1494 D3DPSREGISTER_RefractColor = 29,
1495 D3DPSREGISTER_Saturation = 30,
1496 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1497 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1498 D3DPSREGISTER_ScreenToDepth = 33,
1499 D3DPSREGISTER_ShadowMap_Parameters = 34,
1500 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1501 D3DPSREGISTER_SpecularPower = 36,
1502 D3DPSREGISTER_UserVec1 = 37,
1503 D3DPSREGISTER_UserVec2 = 38,
1504 D3DPSREGISTER_UserVec3 = 39,
1505 D3DPSREGISTER_UserVec4 = 40,
1506 D3DPSREGISTER_ViewTintColor = 41,
1507 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1508 D3DPSREGISTER_BloomColorSubtract = 43,
1509 D3DPSREGISTER_ViewToLight = 44, // float4x4
1510 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1511 D3DPSREGISTER_NormalmapScrollBlend = 52,
1512 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1513 D3DPSREGISTER_OffsetMapping_Bias = 54,
1518 /// information about each possible shader permutation
1519 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1520 /// currently selected permutation
1521 r_hlsl_permutation_t *r_hlsl_permutation;
1522 /// storage for permutations linked in the hash table
1523 memexpandablearray_t r_hlsl_permutationarray;
1525 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1527 //unsigned int hashdepth = 0;
1528 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1529 r_hlsl_permutation_t *p;
1530 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1532 if (p->mode == mode && p->permutation == permutation)
1534 //if (hashdepth > 10)
1535 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1540 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1542 p->permutation = permutation;
1543 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1544 r_hlsl_permutationhash[mode][hashindex] = p;
1545 //if (hashdepth > 10)
1546 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1551 //#include <d3dx9shader.h>
1552 //#include <d3dx9mesh.h>
1554 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1556 DWORD *vsbin = NULL;
1557 DWORD *psbin = NULL;
1558 fs_offset_t vsbinsize;
1559 fs_offset_t psbinsize;
1560 // IDirect3DVertexShader9 *vs = NULL;
1561 // IDirect3DPixelShader9 *ps = NULL;
1562 ID3DXBuffer *vslog = NULL;
1563 ID3DXBuffer *vsbuffer = NULL;
1564 ID3DXConstantTable *vsconstanttable = NULL;
1565 ID3DXBuffer *pslog = NULL;
1566 ID3DXBuffer *psbuffer = NULL;
1567 ID3DXConstantTable *psconstanttable = NULL;
1570 char temp[MAX_INPUTLINE];
1571 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1573 qboolean debugshader = gl_paranoid.integer != 0;
1574 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1575 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1578 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1579 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1581 if ((!vsbin && vertstring) || (!psbin && fragstring))
1583 const char* dllnames_d3dx9 [] =
1607 dllhandle_t d3dx9_dll = NULL;
1608 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1609 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1610 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1611 dllfunction_t d3dx9_dllfuncs[] =
1613 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1614 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1615 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1618 // 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...
1619 #ifndef ID3DXBuffer_GetBufferPointer
1620 #if !defined(__cplusplus) || defined(CINTERFACE)
1621 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1622 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1623 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1625 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1626 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1627 #define ID3DXBuffer_Release(p) (p)->Release()
1630 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1632 DWORD shaderflags = 0;
1634 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1635 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1636 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1637 if (vertstring && vertstring[0])
1641 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1642 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1645 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1648 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1649 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1650 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1651 ID3DXBuffer_Release(vsbuffer);
1655 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1656 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1657 ID3DXBuffer_Release(vslog);
1660 if (fragstring && fragstring[0])
1664 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1665 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1668 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1671 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1672 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1673 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1674 ID3DXBuffer_Release(psbuffer);
1678 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1679 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1680 ID3DXBuffer_Release(pslog);
1683 Sys_UnloadLibrary(&d3dx9_dll);
1686 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1690 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1691 if (FAILED(vsresult))
1692 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1693 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1694 if (FAILED(psresult))
1695 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1697 // free the shader data
1698 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1699 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1702 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1705 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1706 int vertstring_length = 0;
1707 int geomstring_length = 0;
1708 int fragstring_length = 0;
1711 char *vertstring, *geomstring, *fragstring;
1712 char permutationname[256];
1713 char cachename[256];
1714 int vertstrings_count = 0;
1715 int geomstrings_count = 0;
1716 int fragstrings_count = 0;
1717 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1718 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1719 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1724 p->vertexshader = NULL;
1725 p->pixelshader = NULL;
1727 permutationname[0] = 0;
1729 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1731 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1732 strlcat(cachename, "hlsl/", sizeof(cachename));
1734 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1735 vertstrings_count = 0;
1736 geomstrings_count = 0;
1737 fragstrings_count = 0;
1738 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1739 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1740 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1742 // the first pretext is which type of shader to compile as
1743 // (later these will all be bound together as a program object)
1744 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1745 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1746 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1748 // the second pretext is the mode (for example a light source)
1749 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1750 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1751 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1752 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1753 strlcat(cachename, modeinfo->name, sizeof(cachename));
1755 // now add all the permutation pretexts
1756 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1758 if (permutation & (1<<i))
1760 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1761 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1762 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1763 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1764 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1768 // keep line numbers correct
1769 vertstrings_list[vertstrings_count++] = "\n";
1770 geomstrings_list[geomstrings_count++] = "\n";
1771 fragstrings_list[fragstrings_count++] = "\n";
1776 R_CompileShader_AddStaticParms(mode, permutation);
1777 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1778 vertstrings_count += shaderstaticparms_count;
1779 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1780 geomstrings_count += shaderstaticparms_count;
1781 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1782 fragstrings_count += shaderstaticparms_count;
1784 // replace spaces in the cachename with _ characters
1785 for (i = 0;cachename[i];i++)
1786 if (cachename[i] == ' ')
1789 // now append the shader text itself
1790 vertstrings_list[vertstrings_count++] = sourcestring;
1791 geomstrings_list[geomstrings_count++] = sourcestring;
1792 fragstrings_list[fragstrings_count++] = sourcestring;
1794 vertstring_length = 0;
1795 for (i = 0;i < vertstrings_count;i++)
1796 vertstring_length += (int)strlen(vertstrings_list[i]);
1797 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1798 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1799 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1801 geomstring_length = 0;
1802 for (i = 0;i < geomstrings_count;i++)
1803 geomstring_length += (int)strlen(geomstrings_list[i]);
1804 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1805 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1806 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1808 fragstring_length = 0;
1809 for (i = 0;i < fragstrings_count;i++)
1810 fragstring_length += (int)strlen(fragstrings_list[i]);
1811 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1812 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1813 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1815 // try to load the cached shader, or generate one
1816 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1818 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1819 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1821 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1825 Mem_Free(vertstring);
1827 Mem_Free(geomstring);
1829 Mem_Free(fragstring);
1831 Mem_Free(sourcestring);
1834 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1835 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1836 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);}
1837 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);}
1838 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);}
1839 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);}
1841 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1842 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1843 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);}
1844 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);}
1845 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);}
1846 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);}
1848 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1850 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1851 if (r_hlsl_permutation != perm)
1853 r_hlsl_permutation = perm;
1854 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1856 if (!r_hlsl_permutation->compiled)
1857 R_HLSL_CompilePermutation(perm, mode, permutation);
1858 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1860 // remove features until we find a valid permutation
1862 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1864 // reduce i more quickly whenever it would not remove any bits
1865 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1866 if (!(permutation & j))
1869 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1870 if (!r_hlsl_permutation->compiled)
1871 R_HLSL_CompilePermutation(perm, mode, permutation);
1872 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1875 if (i >= SHADERPERMUTATION_COUNT)
1877 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1878 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1879 return; // no bit left to clear, entire mode is broken
1883 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1884 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1886 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1887 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1888 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1892 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1894 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1895 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1896 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1897 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1900 void R_GLSL_Restart_f(void)
1902 unsigned int i, limit;
1903 if (glslshaderstring)
1904 Mem_Free(glslshaderstring);
1905 glslshaderstring = NULL;
1906 if (hlslshaderstring)
1907 Mem_Free(hlslshaderstring);
1908 hlslshaderstring = NULL;
1909 switch(vid.renderpath)
1911 case RENDERPATH_D3D9:
1914 r_hlsl_permutation_t *p;
1915 r_hlsl_permutation = NULL;
1916 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1917 for (i = 0;i < limit;i++)
1919 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1921 if (p->vertexshader)
1922 IDirect3DVertexShader9_Release(p->vertexshader);
1924 IDirect3DPixelShader9_Release(p->pixelshader);
1925 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1928 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1932 case RENDERPATH_D3D10:
1933 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1935 case RENDERPATH_D3D11:
1936 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1938 case RENDERPATH_GL20:
1939 case RENDERPATH_GLES2:
1941 r_glsl_permutation_t *p;
1942 r_glsl_permutation = NULL;
1943 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1944 for (i = 0;i < limit;i++)
1946 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1948 GL_Backend_FreeProgram(p->program);
1949 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1952 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1955 case RENDERPATH_GL11:
1956 case RENDERPATH_GL13:
1957 case RENDERPATH_GLES1:
1959 case RENDERPATH_SOFT:
1964 static void R_GLSL_DumpShader_f(void)
1966 int i, language, mode, dupe;
1968 shadermodeinfo_t *modeinfo;
1971 for (language = 0;language < 2;language++)
1973 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1974 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1976 // don't dump the same file multiple times (most or all shaders come from the same file)
1977 for (dupe = mode - 1;dupe >= 0;dupe--)
1978 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1982 text = R_GetShaderText(modeinfo[mode].filename, false, true);
1985 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1988 FS_Print(file, "/* The engine may define the following macros:\n");
1989 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1990 for (i = 0;i < SHADERMODE_COUNT;i++)
1991 FS_Print(file, modeinfo[i].pretext);
1992 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1993 FS_Print(file, shaderpermutationinfo[i].pretext);
1994 FS_Print(file, "*/\n");
1995 FS_Print(file, text);
1997 Con_Printf("%s written\n", modeinfo[mode].filename);
2000 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2006 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2008 unsigned int permutation = 0;
2009 if (r_trippy.integer && !notrippy)
2010 permutation |= SHADERPERMUTATION_TRIPPY;
2011 permutation |= SHADERPERMUTATION_VIEWTINT;
2013 permutation |= SHADERPERMUTATION_DIFFUSE;
2015 permutation |= SHADERPERMUTATION_SPECULAR;
2016 if (texturemode == GL_MODULATE)
2017 permutation |= SHADERPERMUTATION_COLORMAPPING;
2018 else if (texturemode == GL_ADD)
2019 permutation |= SHADERPERMUTATION_GLOW;
2020 else if (texturemode == GL_DECAL)
2021 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2022 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2023 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2024 if (suppresstexalpha)
2025 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2027 texturemode = GL_MODULATE;
2028 if (vid.allowalphatocoverage)
2029 GL_AlphaToCoverage(false);
2030 switch (vid.renderpath)
2032 case RENDERPATH_D3D9:
2034 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2035 R_Mesh_TexBind(GL20TU_FIRST , first );
2036 R_Mesh_TexBind(GL20TU_SECOND, second);
2037 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2038 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2041 case RENDERPATH_D3D10:
2042 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2044 case RENDERPATH_D3D11:
2045 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2047 case RENDERPATH_GL20:
2048 case RENDERPATH_GLES2:
2049 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2050 if (r_glsl_permutation->tex_Texture_First >= 0)
2051 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2052 if (r_glsl_permutation->tex_Texture_Second >= 0)
2053 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2054 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2055 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2057 case RENDERPATH_GL13:
2058 case RENDERPATH_GLES1:
2059 R_Mesh_TexBind(0, first );
2060 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2061 R_Mesh_TexMatrix(0, NULL);
2062 R_Mesh_TexBind(1, second);
2065 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2066 R_Mesh_TexMatrix(1, NULL);
2069 case RENDERPATH_GL11:
2070 R_Mesh_TexBind(0, first );
2071 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2072 R_Mesh_TexMatrix(0, NULL);
2074 case RENDERPATH_SOFT:
2075 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2076 R_Mesh_TexBind(GL20TU_FIRST , first );
2077 R_Mesh_TexBind(GL20TU_SECOND, second);
2082 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2084 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2087 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2089 unsigned int permutation = 0;
2090 if (r_trippy.integer && !notrippy)
2091 permutation |= SHADERPERMUTATION_TRIPPY;
2093 permutation |= SHADERPERMUTATION_DEPTHRGB;
2095 permutation |= SHADERPERMUTATION_SKELETAL;
2097 if (vid.allowalphatocoverage)
2098 GL_AlphaToCoverage(false);
2099 switch (vid.renderpath)
2101 case RENDERPATH_D3D9:
2103 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2106 case RENDERPATH_D3D10:
2107 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2109 case RENDERPATH_D3D11:
2110 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2112 case RENDERPATH_GL20:
2113 case RENDERPATH_GLES2:
2114 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2115 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2116 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);
2119 case RENDERPATH_GL13:
2120 case RENDERPATH_GLES1:
2121 R_Mesh_TexBind(0, 0);
2122 R_Mesh_TexBind(1, 0);
2124 case RENDERPATH_GL11:
2125 R_Mesh_TexBind(0, 0);
2127 case RENDERPATH_SOFT:
2128 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2133 extern qboolean r_shadow_usingdeferredprepass;
2134 extern rtexture_t *r_shadow_attenuationgradienttexture;
2135 extern rtexture_t *r_shadow_attenuation2dtexture;
2136 extern rtexture_t *r_shadow_attenuation3dtexture;
2137 extern qboolean r_shadow_usingshadowmap2d;
2138 extern qboolean r_shadow_usingshadowmaportho;
2139 extern float r_shadow_modelshadowmap_texturescale[4];
2140 extern float r_shadow_modelshadowmap_parameters[4];
2141 extern float r_shadow_lightshadowmap_texturescale[4];
2142 extern float r_shadow_lightshadowmap_parameters[4];
2143 extern qboolean r_shadow_shadowmapvsdct;
2144 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2145 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2146 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2147 extern matrix4x4_t r_shadow_shadowmapmatrix;
2148 extern int r_shadow_prepass_width;
2149 extern int r_shadow_prepass_height;
2150 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2151 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2152 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2153 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2155 #define BLENDFUNC_ALLOWS_COLORMOD 1
2156 #define BLENDFUNC_ALLOWS_FOG 2
2157 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2158 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2159 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2160 static int R_BlendFuncFlags(int src, int dst)
2164 // a blendfunc allows colormod if:
2165 // a) it can never keep the destination pixel invariant, or
2166 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2167 // this is to prevent unintended side effects from colormod
2169 // a blendfunc allows fog if:
2170 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2171 // this is to prevent unintended side effects from fog
2173 // these checks are the output of fogeval.pl
2175 r |= BLENDFUNC_ALLOWS_COLORMOD;
2176 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2177 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2178 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2180 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2181 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2182 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2183 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2184 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2185 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2186 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2187 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2188 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2189 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2190 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2191 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2193 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2194 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2195 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2196 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2201 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)
2203 // select a permutation of the lighting shader appropriate to this
2204 // combination of texture, entity, light source, and fogging, only use the
2205 // minimum features necessary to avoid wasting rendering time in the
2206 // fragment shader on features that are not being used
2207 unsigned int permutation = 0;
2208 unsigned int mode = 0;
2210 static float dummy_colormod[3] = {1, 1, 1};
2211 float *colormod = rsurface.colormod;
2213 matrix4x4_t tempmatrix;
2214 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2215 if (r_trippy.integer && !notrippy)
2216 permutation |= SHADERPERMUTATION_TRIPPY;
2217 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2218 permutation |= SHADERPERMUTATION_ALPHAKILL;
2219 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2220 permutation |= SHADERPERMUTATION_OCCLUDE;
2221 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2222 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2223 if (rsurfacepass == RSURFPASS_BACKGROUND)
2225 // distorted background
2226 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2228 mode = SHADERMODE_WATER;
2229 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2230 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2231 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2233 // this is the right thing to do for wateralpha
2234 GL_BlendFunc(GL_ONE, GL_ZERO);
2235 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2239 // this is the right thing to do for entity alpha
2240 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2244 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2246 mode = SHADERMODE_REFRACTION;
2247 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2248 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2249 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2250 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2254 mode = SHADERMODE_GENERIC;
2255 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2256 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2257 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2259 if (vid.allowalphatocoverage)
2260 GL_AlphaToCoverage(false);
2262 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2264 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2266 switch(rsurface.texture->offsetmapping)
2268 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2269 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2270 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2271 case OFFSETMAPPING_OFF: break;
2274 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2275 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2276 // normalmap (deferred prepass), may use alpha test on diffuse
2277 mode = SHADERMODE_DEFERREDGEOMETRY;
2278 GL_BlendFunc(GL_ONE, GL_ZERO);
2279 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2280 if (vid.allowalphatocoverage)
2281 GL_AlphaToCoverage(false);
2283 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2285 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2287 switch(rsurface.texture->offsetmapping)
2289 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2290 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2291 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2292 case OFFSETMAPPING_OFF: break;
2295 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2296 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2297 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2298 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2300 mode = SHADERMODE_LIGHTSOURCE;
2301 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2302 permutation |= SHADERPERMUTATION_CUBEFILTER;
2303 if (diffusescale > 0)
2304 permutation |= SHADERPERMUTATION_DIFFUSE;
2305 if (specularscale > 0)
2306 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2307 if (r_refdef.fogenabled)
2308 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2309 if (rsurface.texture->colormapping)
2310 permutation |= SHADERPERMUTATION_COLORMAPPING;
2311 if (r_shadow_usingshadowmap2d)
2313 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2314 if(r_shadow_shadowmapvsdct)
2315 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2317 if (r_shadow_shadowmap2ddepthbuffer)
2318 permutation |= SHADERPERMUTATION_DEPTHRGB;
2320 if (rsurface.texture->reflectmasktexture)
2321 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2322 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2323 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2324 if (vid.allowalphatocoverage)
2325 GL_AlphaToCoverage(false);
2327 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2329 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2331 switch(rsurface.texture->offsetmapping)
2333 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2334 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2335 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2336 case OFFSETMAPPING_OFF: break;
2339 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2340 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2341 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2342 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2343 // unshaded geometry (fullbright or ambient model lighting)
2344 mode = SHADERMODE_FLATCOLOR;
2345 ambientscale = diffusescale = specularscale = 0;
2346 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2347 permutation |= SHADERPERMUTATION_GLOW;
2348 if (r_refdef.fogenabled)
2349 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2350 if (rsurface.texture->colormapping)
2351 permutation |= SHADERPERMUTATION_COLORMAPPING;
2352 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2354 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2355 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2357 if (r_shadow_shadowmap2ddepthbuffer)
2358 permutation |= SHADERPERMUTATION_DEPTHRGB;
2360 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2361 permutation |= SHADERPERMUTATION_REFLECTION;
2362 if (rsurface.texture->reflectmasktexture)
2363 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2364 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2365 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2366 // when using alphatocoverage, we don't need alphakill
2367 if (vid.allowalphatocoverage)
2369 if (r_transparent_alphatocoverage.integer)
2371 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2372 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2375 GL_AlphaToCoverage(false);
2378 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2380 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2382 switch(rsurface.texture->offsetmapping)
2384 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2385 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2386 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2387 case OFFSETMAPPING_OFF: break;
2390 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2391 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2392 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2393 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2394 // directional model lighting
2395 mode = SHADERMODE_LIGHTDIRECTION;
2396 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2397 permutation |= SHADERPERMUTATION_GLOW;
2398 permutation |= SHADERPERMUTATION_DIFFUSE;
2399 if (specularscale > 0)
2400 permutation |= SHADERPERMUTATION_SPECULAR;
2401 if (r_refdef.fogenabled)
2402 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2403 if (rsurface.texture->colormapping)
2404 permutation |= SHADERPERMUTATION_COLORMAPPING;
2405 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2407 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2408 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2410 if (r_shadow_shadowmap2ddepthbuffer)
2411 permutation |= SHADERPERMUTATION_DEPTHRGB;
2413 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2414 permutation |= SHADERPERMUTATION_REFLECTION;
2415 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2416 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2417 if (rsurface.texture->reflectmasktexture)
2418 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2419 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2421 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2422 if (r_shadow_bouncegrid_state.directional)
2423 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2425 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2426 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2427 // when using alphatocoverage, we don't need alphakill
2428 if (vid.allowalphatocoverage)
2430 if (r_transparent_alphatocoverage.integer)
2432 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2433 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2436 GL_AlphaToCoverage(false);
2439 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2441 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2443 switch(rsurface.texture->offsetmapping)
2445 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2446 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2447 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2448 case OFFSETMAPPING_OFF: break;
2451 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2452 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2453 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2454 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2455 // ambient model lighting
2456 mode = SHADERMODE_LIGHTDIRECTION;
2457 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2458 permutation |= SHADERPERMUTATION_GLOW;
2459 if (r_refdef.fogenabled)
2460 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2461 if (rsurface.texture->colormapping)
2462 permutation |= SHADERPERMUTATION_COLORMAPPING;
2463 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2465 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2466 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2468 if (r_shadow_shadowmap2ddepthbuffer)
2469 permutation |= SHADERPERMUTATION_DEPTHRGB;
2471 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2472 permutation |= SHADERPERMUTATION_REFLECTION;
2473 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2474 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2475 if (rsurface.texture->reflectmasktexture)
2476 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2477 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2479 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2480 if (r_shadow_bouncegrid_state.directional)
2481 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2483 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2484 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2485 // when using alphatocoverage, we don't need alphakill
2486 if (vid.allowalphatocoverage)
2488 if (r_transparent_alphatocoverage.integer)
2490 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2491 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2494 GL_AlphaToCoverage(false);
2499 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2501 switch(rsurface.texture->offsetmapping)
2503 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2504 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2505 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2506 case OFFSETMAPPING_OFF: break;
2509 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2510 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2511 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2512 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2514 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2515 permutation |= SHADERPERMUTATION_GLOW;
2516 if (r_refdef.fogenabled)
2517 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2518 if (rsurface.texture->colormapping)
2519 permutation |= SHADERPERMUTATION_COLORMAPPING;
2520 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2522 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2523 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2525 if (r_shadow_shadowmap2ddepthbuffer)
2526 permutation |= SHADERPERMUTATION_DEPTHRGB;
2528 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2529 permutation |= SHADERPERMUTATION_REFLECTION;
2530 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2531 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2532 if (rsurface.texture->reflectmasktexture)
2533 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2534 if (FAKELIGHT_ENABLED)
2536 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2537 mode = SHADERMODE_FAKELIGHT;
2538 permutation |= SHADERPERMUTATION_DIFFUSE;
2539 if (specularscale > 0)
2540 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2542 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2544 // deluxemapping (light direction texture)
2545 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2546 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2548 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2549 permutation |= SHADERPERMUTATION_DIFFUSE;
2550 if (specularscale > 0)
2551 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2553 else if (r_glsl_deluxemapping.integer >= 2)
2555 // fake deluxemapping (uniform light direction in tangentspace)
2556 if (rsurface.uselightmaptexture)
2557 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2559 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2560 permutation |= SHADERPERMUTATION_DIFFUSE;
2561 if (specularscale > 0)
2562 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2564 else if (rsurface.uselightmaptexture)
2566 // ordinary lightmapping (q1bsp, q3bsp)
2567 mode = SHADERMODE_LIGHTMAP;
2571 // ordinary vertex coloring (q3bsp)
2572 mode = SHADERMODE_VERTEXCOLOR;
2574 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2576 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2577 if (r_shadow_bouncegrid_state.directional)
2578 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2580 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2581 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2582 // when using alphatocoverage, we don't need alphakill
2583 if (vid.allowalphatocoverage)
2585 if (r_transparent_alphatocoverage.integer)
2587 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2588 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2591 GL_AlphaToCoverage(false);
2594 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2595 colormod = dummy_colormod;
2596 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2597 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2598 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2599 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2600 switch(vid.renderpath)
2602 case RENDERPATH_D3D9:
2604 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);
2605 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2606 R_SetupShader_SetPermutationHLSL(mode, permutation);
2607 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2608 if (mode == SHADERMODE_LIGHTSOURCE)
2610 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2611 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2615 if (mode == SHADERMODE_LIGHTDIRECTION)
2617 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2620 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2621 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2622 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2623 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2624 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2626 if (mode == SHADERMODE_LIGHTSOURCE)
2628 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2629 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2630 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2631 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2632 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2634 // additive passes are only darkened by fog, not tinted
2635 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2636 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2640 if (mode == SHADERMODE_FLATCOLOR)
2642 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2644 else if (mode == SHADERMODE_LIGHTDIRECTION)
2646 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]);
2647 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2648 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);
2649 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2650 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2651 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2652 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2656 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2657 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2658 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);
2659 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2660 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2662 // additive passes are only darkened by fog, not tinted
2663 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2664 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2666 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2667 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);
2668 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2669 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2670 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2671 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2672 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2673 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2674 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2675 if (mode == SHADERMODE_WATER)
2676 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2678 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2680 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2681 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2685 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2686 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2688 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2689 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));
2690 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2691 if (rsurface.texture->pantstexture)
2692 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2694 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2695 if (rsurface.texture->shirttexture)
2696 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2698 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2699 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2700 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2701 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2702 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2703 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2704 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2705 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2706 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2707 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2709 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2710 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2711 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2712 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2714 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2715 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2716 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2717 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2718 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2719 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2720 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2721 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2722 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2723 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2724 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2725 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2726 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2727 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2728 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2729 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2730 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2731 if (rsurfacepass == RSURFPASS_BACKGROUND)
2733 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2734 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2735 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2739 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2741 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2742 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2743 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2744 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2746 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2747 if (rsurface.rtlight)
2749 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2750 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2755 case RENDERPATH_D3D10:
2756 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2758 case RENDERPATH_D3D11:
2759 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2761 case RENDERPATH_GL20:
2762 case RENDERPATH_GLES2:
2763 if (!vid.useinterleavedarrays)
2765 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);
2766 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2767 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2768 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2769 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2770 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2771 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2772 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2773 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2774 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2775 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2779 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);
2780 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2782 // this has to be after RSurf_PrepareVerticesForBatch
2783 if (rsurface.batchskeletaltransform3x4buffer)
2784 permutation |= SHADERPERMUTATION_SKELETAL;
2785 R_SetupShader_SetPermutationGLSL(mode, permutation);
2786 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2787 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);
2789 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2790 if (mode == SHADERMODE_LIGHTSOURCE)
2792 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2793 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2794 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2795 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2796 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2797 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);
2799 // additive passes are only darkened by fog, not tinted
2800 if (r_glsl_permutation->loc_FogColor >= 0)
2801 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2802 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);
2806 if (mode == SHADERMODE_FLATCOLOR)
2808 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2810 else if (mode == SHADERMODE_LIGHTDIRECTION)
2812 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]);
2813 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]);
2814 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);
2815 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2816 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2817 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]);
2818 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]);
2822 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]);
2823 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]);
2824 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);
2825 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2826 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2828 // additive passes are only darkened by fog, not tinted
2829 if (r_glsl_permutation->loc_FogColor >= 0)
2831 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2832 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2834 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2836 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);
2837 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]);
2838 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]);
2839 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]);
2840 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]);
2841 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2842 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2843 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);
2844 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]);
2846 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2847 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2848 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2849 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2851 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2852 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2856 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2857 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2860 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2861 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));
2862 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2863 if (r_glsl_permutation->loc_Color_Pants >= 0)
2865 if (rsurface.texture->pantstexture)
2866 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2868 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2870 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2872 if (rsurface.texture->shirttexture)
2873 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2875 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2877 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]);
2878 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2879 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2880 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2881 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2882 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2883 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2884 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2885 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2887 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);
2888 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2889 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]);
2890 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2891 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2892 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2894 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2895 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2896 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2897 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2898 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2899 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2900 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2901 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2902 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2903 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2904 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2905 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2906 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2907 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2908 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);
2909 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2910 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2911 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2912 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2913 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2914 if (rsurfacepass == RSURFPASS_BACKGROUND)
2916 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);
2917 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);
2918 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);
2922 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);
2924 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2925 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2926 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2927 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2929 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2930 if (rsurface.rtlight)
2932 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2933 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2936 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2939 case RENDERPATH_GL11:
2940 case RENDERPATH_GL13:
2941 case RENDERPATH_GLES1:
2943 case RENDERPATH_SOFT:
2944 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);
2945 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2946 R_SetupShader_SetPermutationSoft(mode, permutation);
2947 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2948 if (mode == SHADERMODE_LIGHTSOURCE)
2950 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2951 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2952 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2953 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2954 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2955 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2957 // additive passes are only darkened by fog, not tinted
2958 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2959 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2963 if (mode == SHADERMODE_FLATCOLOR)
2965 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2967 else if (mode == SHADERMODE_LIGHTDIRECTION)
2969 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]);
2970 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2971 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);
2972 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2973 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2974 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]);
2975 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2979 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2980 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2981 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);
2982 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2983 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2985 // additive passes are only darkened by fog, not tinted
2986 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2987 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2989 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2990 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);
2991 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]);
2992 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]);
2993 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]);
2994 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]);
2995 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2996 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2997 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2998 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
3000 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3001 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3002 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3003 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3005 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
3006 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
3010 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3011 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3014 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3015 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));
3016 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3017 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3019 if (rsurface.texture->pantstexture)
3020 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3022 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3024 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3026 if (rsurface.texture->shirttexture)
3027 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3029 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3031 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3032 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3033 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3034 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3035 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3036 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3037 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3038 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3039 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3041 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3042 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3043 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3044 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3046 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3047 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3048 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3049 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3050 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3051 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3052 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3053 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3054 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3055 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3056 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3057 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3058 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3059 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3060 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3061 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3062 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3063 if (rsurfacepass == RSURFPASS_BACKGROUND)
3065 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3066 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3067 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3071 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3073 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3074 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3075 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3076 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3078 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3079 if (rsurface.rtlight)
3081 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3082 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3089 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3091 // select a permutation of the lighting shader appropriate to this
3092 // combination of texture, entity, light source, and fogging, only use the
3093 // minimum features necessary to avoid wasting rendering time in the
3094 // fragment shader on features that are not being used
3095 unsigned int permutation = 0;
3096 unsigned int mode = 0;
3097 const float *lightcolorbase = rtlight->currentcolor;
3098 float ambientscale = rtlight->ambientscale;
3099 float diffusescale = rtlight->diffusescale;
3100 float specularscale = rtlight->specularscale;
3101 // this is the location of the light in view space
3102 vec3_t viewlightorigin;
3103 // this transforms from view space (camera) to light space (cubemap)
3104 matrix4x4_t viewtolight;
3105 matrix4x4_t lighttoview;
3106 float viewtolight16f[16];
3108 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3109 if (rtlight->currentcubemap != r_texture_whitecube)
3110 permutation |= SHADERPERMUTATION_CUBEFILTER;
3111 if (diffusescale > 0)
3112 permutation |= SHADERPERMUTATION_DIFFUSE;
3113 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3114 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3115 if (r_shadow_usingshadowmap2d)
3117 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3118 if (r_shadow_shadowmapvsdct)
3119 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3121 if (r_shadow_shadowmap2ddepthbuffer)
3122 permutation |= SHADERPERMUTATION_DEPTHRGB;
3124 if (vid.allowalphatocoverage)
3125 GL_AlphaToCoverage(false);
3126 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3127 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3128 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3129 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3130 switch(vid.renderpath)
3132 case RENDERPATH_D3D9:
3134 R_SetupShader_SetPermutationHLSL(mode, permutation);
3135 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3136 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3137 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3138 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3139 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3140 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3141 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3142 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);
3143 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3144 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3146 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3147 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3148 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3149 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3150 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3153 case RENDERPATH_D3D10:
3154 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3156 case RENDERPATH_D3D11:
3157 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3159 case RENDERPATH_GL20:
3160 case RENDERPATH_GLES2:
3161 R_SetupShader_SetPermutationGLSL(mode, permutation);
3162 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3163 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3164 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3165 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3166 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3167 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3168 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3169 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);
3170 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]);
3171 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3173 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3174 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3175 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3176 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3177 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3179 case RENDERPATH_GL11:
3180 case RENDERPATH_GL13:
3181 case RENDERPATH_GLES1:
3183 case RENDERPATH_SOFT:
3184 R_SetupShader_SetPermutationGLSL(mode, permutation);
3185 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3186 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3187 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3188 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3189 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3190 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3191 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3192 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);
3193 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3194 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3196 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3197 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3198 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3199 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3200 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3205 #define SKINFRAME_HASH 1024
3209 unsigned int loadsequence; // incremented each level change
3210 memexpandablearray_t array;
3211 skinframe_t *hash[SKINFRAME_HASH];
3214 r_skinframe_t r_skinframe;
3216 void R_SkinFrame_PrepareForPurge(void)
3218 r_skinframe.loadsequence++;
3219 // wrap it without hitting zero
3220 if (r_skinframe.loadsequence >= 200)
3221 r_skinframe.loadsequence = 1;
3224 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3228 // mark the skinframe as used for the purging code
3229 skinframe->loadsequence = r_skinframe.loadsequence;
3232 void R_SkinFrame_Purge(void)
3236 for (i = 0;i < SKINFRAME_HASH;i++)
3238 for (s = r_skinframe.hash[i];s;s = s->next)
3240 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3242 if (s->merged == s->base)
3244 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3245 R_PurgeTexture(s->stain );s->stain = NULL;
3246 R_PurgeTexture(s->merged);s->merged = NULL;
3247 R_PurgeTexture(s->base );s->base = NULL;
3248 R_PurgeTexture(s->pants );s->pants = NULL;
3249 R_PurgeTexture(s->shirt );s->shirt = NULL;
3250 R_PurgeTexture(s->nmap );s->nmap = NULL;
3251 R_PurgeTexture(s->gloss );s->gloss = NULL;
3252 R_PurgeTexture(s->glow );s->glow = NULL;
3253 R_PurgeTexture(s->fog );s->fog = NULL;
3254 R_PurgeTexture(s->reflect);s->reflect = NULL;
3255 s->loadsequence = 0;
3261 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3263 char basename[MAX_QPATH];
3265 Image_StripImageExtension(name, basename, sizeof(basename));
3267 if( last == NULL ) {
3269 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3270 item = r_skinframe.hash[hashindex];
3275 // linearly search through the hash bucket
3276 for( ; item ; item = item->next ) {
3277 if( !strcmp( item->basename, basename ) ) {
3284 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3288 char basename[MAX_QPATH];
3290 Image_StripImageExtension(name, basename, sizeof(basename));
3292 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3293 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3294 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3298 rtexture_t *dyntexture;
3299 // check whether its a dynamic texture
3300 dyntexture = CL_GetDynTexture( basename );
3301 if (!add && !dyntexture)
3303 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3304 memset(item, 0, sizeof(*item));
3305 strlcpy(item->basename, basename, sizeof(item->basename));
3306 item->base = dyntexture; // either NULL or dyntexture handle
3307 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3308 item->comparewidth = comparewidth;
3309 item->compareheight = compareheight;
3310 item->comparecrc = comparecrc;
3311 item->next = r_skinframe.hash[hashindex];
3312 r_skinframe.hash[hashindex] = item;
3314 else if (textureflags & TEXF_FORCE_RELOAD)
3316 rtexture_t *dyntexture;
3317 // check whether its a dynamic texture
3318 dyntexture = CL_GetDynTexture( basename );
3319 if (!add && !dyntexture)
3321 if (item->merged == item->base)
3322 item->merged = NULL;
3323 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3324 R_PurgeTexture(item->stain );item->stain = NULL;
3325 R_PurgeTexture(item->merged);item->merged = NULL;
3326 R_PurgeTexture(item->base );item->base = NULL;
3327 R_PurgeTexture(item->pants );item->pants = NULL;
3328 R_PurgeTexture(item->shirt );item->shirt = NULL;
3329 R_PurgeTexture(item->nmap );item->nmap = NULL;
3330 R_PurgeTexture(item->gloss );item->gloss = NULL;
3331 R_PurgeTexture(item->glow );item->glow = NULL;
3332 R_PurgeTexture(item->fog );item->fog = NULL;
3333 R_PurgeTexture(item->reflect);item->reflect = NULL;
3334 item->loadsequence = 0;
3336 else if( item->base == NULL )
3338 rtexture_t *dyntexture;
3339 // check whether its a dynamic texture
3340 // 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]
3341 dyntexture = CL_GetDynTexture( basename );
3342 item->base = dyntexture; // either NULL or dyntexture handle
3345 R_SkinFrame_MarkUsed(item);
3349 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3351 unsigned long long avgcolor[5], wsum; \
3359 for(pix = 0; pix < cnt; ++pix) \
3362 for(comp = 0; comp < 3; ++comp) \
3364 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3367 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3369 for(comp = 0; comp < 3; ++comp) \
3370 avgcolor[comp] += getpixel * w; \
3373 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3374 avgcolor[4] += getpixel; \
3376 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3378 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3379 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3380 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3381 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3384 extern cvar_t gl_picmip;
3385 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3388 unsigned char *pixels;
3389 unsigned char *bumppixels;
3390 unsigned char *basepixels = NULL;
3391 int basepixels_width = 0;
3392 int basepixels_height = 0;
3393 skinframe_t *skinframe;
3394 rtexture_t *ddsbase = NULL;
3395 qboolean ddshasalpha = false;
3396 float ddsavgcolor[4];
3397 char basename[MAX_QPATH];
3398 int miplevel = R_PicmipForFlags(textureflags);
3399 int savemiplevel = miplevel;
3403 if (cls.state == ca_dedicated)
3406 // return an existing skinframe if already loaded
3407 // if loading of the first image fails, don't make a new skinframe as it
3408 // would cause all future lookups of this to be missing
3409 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3410 if (skinframe && skinframe->base)
3413 Image_StripImageExtension(name, basename, sizeof(basename));
3415 // check for DDS texture file first
3416 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3418 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3419 if (basepixels == NULL)
3423 // FIXME handle miplevel
3425 if (developer_loading.integer)
3426 Con_Printf("loading skin \"%s\"\n", name);
3428 // we've got some pixels to store, so really allocate this new texture now
3430 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3431 textureflags &= ~TEXF_FORCE_RELOAD;
3432 skinframe->stain = NULL;
3433 skinframe->merged = NULL;
3434 skinframe->base = NULL;
3435 skinframe->pants = NULL;
3436 skinframe->shirt = NULL;
3437 skinframe->nmap = NULL;
3438 skinframe->gloss = NULL;
3439 skinframe->glow = NULL;
3440 skinframe->fog = NULL;
3441 skinframe->reflect = NULL;
3442 skinframe->hasalpha = false;
3443 // we could store the q2animname here too
3447 skinframe->base = ddsbase;
3448 skinframe->hasalpha = ddshasalpha;
3449 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3450 if (r_loadfog && skinframe->hasalpha)
3451 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);
3452 //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]);
3456 basepixels_width = image_width;
3457 basepixels_height = image_height;
3458 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);
3459 if (textureflags & TEXF_ALPHA)
3461 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3463 if (basepixels[j] < 255)
3465 skinframe->hasalpha = true;
3469 if (r_loadfog && skinframe->hasalpha)
3471 // has transparent pixels
3472 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3473 for (j = 0;j < image_width * image_height * 4;j += 4)
3478 pixels[j+3] = basepixels[j+3];
3480 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);
3484 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3486 //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]);
3487 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3488 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3489 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3490 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3496 mymiplevel = savemiplevel;
3497 if (r_loadnormalmap)
3498 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);
3499 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3501 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3502 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3503 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3504 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3507 // _norm is the name used by tenebrae and has been adopted as standard
3508 if (r_loadnormalmap && skinframe->nmap == NULL)
3510 mymiplevel = savemiplevel;
3511 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3513 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);
3517 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3519 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3520 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3521 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);
3523 Mem_Free(bumppixels);
3525 else if (r_shadow_bumpscale_basetexture.value > 0)
3527 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3528 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3529 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);
3533 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3534 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3538 // _luma is supported only for tenebrae compatibility
3539 // _glow is the preferred name
3540 mymiplevel = savemiplevel;
3541 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))))
3543 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);
3545 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3546 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3548 Mem_Free(pixels);pixels = NULL;
3551 mymiplevel = savemiplevel;
3552 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3554 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);
3556 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3557 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3563 mymiplevel = savemiplevel;
3564 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3566 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);
3568 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3569 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3575 mymiplevel = savemiplevel;
3576 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3578 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);
3580 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3581 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3587 mymiplevel = savemiplevel;
3588 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3590 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);
3592 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3593 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3600 Mem_Free(basepixels);
3605 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3606 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3609 skinframe_t *skinframe;
3612 if (cls.state == ca_dedicated)
3615 // if already loaded just return it, otherwise make a new skinframe
3616 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3617 if (skinframe->base)
3619 textureflags &= ~TEXF_FORCE_RELOAD;
3621 skinframe->stain = NULL;
3622 skinframe->merged = NULL;
3623 skinframe->base = NULL;
3624 skinframe->pants = NULL;
3625 skinframe->shirt = NULL;
3626 skinframe->nmap = NULL;
3627 skinframe->gloss = NULL;
3628 skinframe->glow = NULL;
3629 skinframe->fog = NULL;
3630 skinframe->reflect = NULL;
3631 skinframe->hasalpha = false;
3633 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3637 if (developer_loading.integer)
3638 Con_Printf("loading 32bit skin \"%s\"\n", name);
3640 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3642 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3643 unsigned char *b = a + width * height * 4;
3644 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3645 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3648 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3649 if (textureflags & TEXF_ALPHA)
3651 for (i = 3;i < width * height * 4;i += 4)
3653 if (skindata[i] < 255)
3655 skinframe->hasalpha = true;
3659 if (r_loadfog && skinframe->hasalpha)
3661 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3662 memcpy(fogpixels, skindata, width * height * 4);
3663 for (i = 0;i < width * height * 4;i += 4)
3664 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3665 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3666 Mem_Free(fogpixels);
3670 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3671 //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]);
3676 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3680 skinframe_t *skinframe;
3682 if (cls.state == ca_dedicated)
3685 // if already loaded just return it, otherwise make a new skinframe
3686 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3687 if (skinframe->base)
3689 //textureflags &= ~TEXF_FORCE_RELOAD;
3691 skinframe->stain = NULL;
3692 skinframe->merged = NULL;
3693 skinframe->base = NULL;
3694 skinframe->pants = NULL;
3695 skinframe->shirt = NULL;
3696 skinframe->nmap = NULL;
3697 skinframe->gloss = NULL;
3698 skinframe->glow = NULL;
3699 skinframe->fog = NULL;
3700 skinframe->reflect = NULL;
3701 skinframe->hasalpha = false;
3703 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3707 if (developer_loading.integer)
3708 Con_Printf("loading quake skin \"%s\"\n", name);
3710 // 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)
3711 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3712 memcpy(skinframe->qpixels, skindata, width*height);
3713 skinframe->qwidth = width;
3714 skinframe->qheight = height;
3717 for (i = 0;i < width * height;i++)
3718 featuresmask |= palette_featureflags[skindata[i]];
3720 skinframe->hasalpha = false;
3723 skinframe->hasalpha = true;
3724 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3725 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3726 skinframe->qgeneratemerged = true;
3727 skinframe->qgeneratebase = skinframe->qhascolormapping;
3728 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3730 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3731 //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]);
3736 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3740 unsigned char *skindata;
3743 if (!skinframe->qpixels)
3746 if (!skinframe->qhascolormapping)
3747 colormapped = false;
3751 if (!skinframe->qgeneratebase)
3756 if (!skinframe->qgeneratemerged)
3760 width = skinframe->qwidth;
3761 height = skinframe->qheight;
3762 skindata = skinframe->qpixels;
3764 if (skinframe->qgeneratenmap)
3766 unsigned char *a, *b;
3767 skinframe->qgeneratenmap = false;
3768 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3769 b = a + width * height * 4;
3770 // use either a custom palette or the quake palette
3771 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3772 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3773 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3777 if (skinframe->qgenerateglow)
3779 skinframe->qgenerateglow = false;
3780 if (skinframe->hasalpha) // fence textures
3781 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 | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow
3783 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
3788 skinframe->qgeneratebase = false;
3789 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);
3790 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);
3791 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);
3795 skinframe->qgeneratemerged = false;
3796 if (skinframe->hasalpha) // fence textures
3797 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, skinframe->glow ? palette_bgra_nofullbrights_transparent : palette_bgra_transparent);
3799 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);
3802 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3804 Mem_Free(skinframe->qpixels);
3805 skinframe->qpixels = NULL;
3809 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)
3812 skinframe_t *skinframe;
3815 if (cls.state == ca_dedicated)
3818 // if already loaded just return it, otherwise make a new skinframe
3819 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3820 if (skinframe->base)
3822 textureflags &= ~TEXF_FORCE_RELOAD;
3824 skinframe->stain = NULL;
3825 skinframe->merged = NULL;
3826 skinframe->base = NULL;
3827 skinframe->pants = NULL;
3828 skinframe->shirt = NULL;
3829 skinframe->nmap = NULL;
3830 skinframe->gloss = NULL;
3831 skinframe->glow = NULL;
3832 skinframe->fog = NULL;
3833 skinframe->reflect = NULL;
3834 skinframe->hasalpha = false;
3836 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3840 if (developer_loading.integer)
3841 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3843 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3844 if (textureflags & TEXF_ALPHA)
3846 for (i = 0;i < width * height;i++)
3848 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3850 skinframe->hasalpha = true;
3854 if (r_loadfog && skinframe->hasalpha)
3855 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3858 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3859 //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]);
3864 skinframe_t *R_SkinFrame_LoadMissing(void)
3866 skinframe_t *skinframe;
3868 if (cls.state == ca_dedicated)
3871 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3872 skinframe->stain = NULL;
3873 skinframe->merged = NULL;
3874 skinframe->base = NULL;
3875 skinframe->pants = NULL;
3876 skinframe->shirt = NULL;
3877 skinframe->nmap = NULL;
3878 skinframe->gloss = NULL;
3879 skinframe->glow = NULL;
3880 skinframe->fog = NULL;
3881 skinframe->reflect = NULL;
3882 skinframe->hasalpha = false;
3884 skinframe->avgcolor[0] = rand() / RAND_MAX;
3885 skinframe->avgcolor[1] = rand() / RAND_MAX;
3886 skinframe->avgcolor[2] = rand() / RAND_MAX;
3887 skinframe->avgcolor[3] = 1;
3892 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3893 typedef struct suffixinfo_s
3896 qboolean flipx, flipy, flipdiagonal;
3899 static suffixinfo_t suffix[3][6] =
3902 {"px", false, false, false},
3903 {"nx", false, false, false},
3904 {"py", false, false, false},
3905 {"ny", false, false, false},
3906 {"pz", false, false, false},
3907 {"nz", false, false, false}
3910 {"posx", false, false, false},
3911 {"negx", false, false, false},
3912 {"posy", false, false, false},
3913 {"negy", false, false, false},
3914 {"posz", false, false, false},
3915 {"negz", false, false, false}
3918 {"rt", true, false, true},
3919 {"lf", false, true, true},
3920 {"ft", true, true, false},
3921 {"bk", false, false, false},
3922 {"up", true, false, true},
3923 {"dn", true, false, true}
3927 static int componentorder[4] = {0, 1, 2, 3};
3929 static rtexture_t *R_LoadCubemap(const char *basename)
3931 int i, j, cubemapsize;
3932 unsigned char *cubemappixels, *image_buffer;
3933 rtexture_t *cubemaptexture;
3935 // must start 0 so the first loadimagepixels has no requested width/height
3937 cubemappixels = NULL;
3938 cubemaptexture = NULL;
3939 // keep trying different suffix groups (posx, px, rt) until one loads
3940 for (j = 0;j < 3 && !cubemappixels;j++)
3942 // load the 6 images in the suffix group
3943 for (i = 0;i < 6;i++)
3945 // generate an image name based on the base and and suffix
3946 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3948 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3950 // an image loaded, make sure width and height are equal
3951 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3953 // if this is the first image to load successfully, allocate the cubemap memory
3954 if (!cubemappixels && image_width >= 1)
3956 cubemapsize = image_width;
3957 // note this clears to black, so unavailable sides are black
3958 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3960 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3962 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);
3965 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3967 Mem_Free(image_buffer);
3971 // if a cubemap loaded, upload it
3974 if (developer_loading.integer)
3975 Con_Printf("loading cubemap \"%s\"\n", basename);
3977 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);
3978 Mem_Free(cubemappixels);
3982 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3983 if (developer_loading.integer)
3985 Con_Printf("(tried tried images ");
3986 for (j = 0;j < 3;j++)
3987 for (i = 0;i < 6;i++)
3988 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3989 Con_Print(" and was unable to find any of them).\n");
3992 return cubemaptexture;
3995 rtexture_t *R_GetCubemap(const char *basename)
3998 for (i = 0;i < r_texture_numcubemaps;i++)
3999 if (r_texture_cubemaps[i] != NULL)
4000 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4001 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4002 if (i >= MAX_CUBEMAPS || !r_main_mempool)
4003 return r_texture_whitecube;
4004 r_texture_numcubemaps++;
4005 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4006 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4007 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4008 return r_texture_cubemaps[i]->texture;
4011 static void R_Main_FreeViewCache(void)
4013 if (r_refdef.viewcache.entityvisible)
4014 Mem_Free(r_refdef.viewcache.entityvisible);
4015 if (r_refdef.viewcache.world_pvsbits)
4016 Mem_Free(r_refdef.viewcache.world_pvsbits);
4017 if (r_refdef.viewcache.world_leafvisible)
4018 Mem_Free(r_refdef.viewcache.world_leafvisible);
4019 if (r_refdef.viewcache.world_surfacevisible)
4020 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4021 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4024 static void R_Main_ResizeViewCache(void)
4026 int numentities = r_refdef.scene.numentities;
4027 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4028 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4029 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4030 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4031 if (r_refdef.viewcache.maxentities < numentities)
4033 r_refdef.viewcache.maxentities = numentities;
4034 if (r_refdef.viewcache.entityvisible)
4035 Mem_Free(r_refdef.viewcache.entityvisible);
4036 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4038 if (r_refdef.viewcache.world_numclusters != numclusters)
4040 r_refdef.viewcache.world_numclusters = numclusters;
4041 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4042 if (r_refdef.viewcache.world_pvsbits)
4043 Mem_Free(r_refdef.viewcache.world_pvsbits);
4044 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4046 if (r_refdef.viewcache.world_numleafs != numleafs)
4048 r_refdef.viewcache.world_numleafs = numleafs;
4049 if (r_refdef.viewcache.world_leafvisible)
4050 Mem_Free(r_refdef.viewcache.world_leafvisible);
4051 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4053 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4055 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4056 if (r_refdef.viewcache.world_surfacevisible)
4057 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4058 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4062 extern rtexture_t *loadingscreentexture;
4063 static void gl_main_start(void)
4065 loadingscreentexture = NULL;
4066 r_texture_blanknormalmap = NULL;
4067 r_texture_white = NULL;
4068 r_texture_grey128 = NULL;
4069 r_texture_black = NULL;
4070 r_texture_whitecube = NULL;
4071 r_texture_normalizationcube = NULL;
4072 r_texture_fogattenuation = NULL;
4073 r_texture_fogheighttexture = NULL;
4074 r_texture_gammaramps = NULL;
4075 r_texture_numcubemaps = 0;
4076 r_uniformbufferalignment = 32;
4078 r_loaddds = r_texture_dds_load.integer != 0;
4079 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4081 switch(vid.renderpath)
4083 case RENDERPATH_GL20:
4084 case RENDERPATH_D3D9:
4085 case RENDERPATH_D3D10:
4086 case RENDERPATH_D3D11:
4087 case RENDERPATH_SOFT:
4088 case RENDERPATH_GLES2:
4089 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4090 Cvar_SetValueQuick(&gl_combine, 1);
4091 Cvar_SetValueQuick(&r_glsl, 1);
4092 r_loadnormalmap = true;
4095 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4096 if (vid.support.arb_uniform_buffer_object)
4097 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4100 case RENDERPATH_GL13:
4101 case RENDERPATH_GLES1:
4102 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4103 Cvar_SetValueQuick(&gl_combine, 1);
4104 Cvar_SetValueQuick(&r_glsl, 0);
4105 r_loadnormalmap = false;
4106 r_loadgloss = false;
4109 case RENDERPATH_GL11:
4110 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4111 Cvar_SetValueQuick(&gl_combine, 0);
4112 Cvar_SetValueQuick(&r_glsl, 0);
4113 r_loadnormalmap = false;
4114 r_loadgloss = false;
4120 R_FrameData_Reset();
4121 R_BufferData_Reset();
4125 memset(r_queries, 0, sizeof(r_queries));
4127 r_qwskincache = NULL;
4128 r_qwskincache_size = 0;
4130 // due to caching of texture_t references, the collision cache must be reset
4131 Collision_Cache_Reset(true);
4133 // set up r_skinframe loading system for textures
4134 memset(&r_skinframe, 0, sizeof(r_skinframe));
4135 r_skinframe.loadsequence = 1;
4136 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4138 r_main_texturepool = R_AllocTexturePool();
4139 R_BuildBlankTextures();
4141 if (vid.support.arb_texture_cube_map)
4144 R_BuildNormalizationCube();
4146 r_texture_fogattenuation = NULL;
4147 r_texture_fogheighttexture = NULL;
4148 r_texture_gammaramps = NULL;
4149 //r_texture_fogintensity = NULL;
4150 memset(&r_fb, 0, sizeof(r_fb));
4151 r_glsl_permutation = NULL;
4152 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4153 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4154 glslshaderstring = NULL;
4156 r_hlsl_permutation = NULL;
4157 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4158 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4160 hlslshaderstring = NULL;
4161 memset(&r_svbsp, 0, sizeof (r_svbsp));
4163 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4164 r_texture_numcubemaps = 0;
4166 r_refdef.fogmasktable_density = 0;
4169 // For Steelstorm Android
4170 // FIXME CACHE the program and reload
4171 // FIXME see possible combinations for SS:BR android
4172 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4173 R_SetupShader_SetPermutationGLSL(0, 12);
4174 R_SetupShader_SetPermutationGLSL(0, 13);
4175 R_SetupShader_SetPermutationGLSL(0, 8388621);
4176 R_SetupShader_SetPermutationGLSL(3, 0);
4177 R_SetupShader_SetPermutationGLSL(3, 2048);
4178 R_SetupShader_SetPermutationGLSL(5, 0);
4179 R_SetupShader_SetPermutationGLSL(5, 2);
4180 R_SetupShader_SetPermutationGLSL(5, 2048);
4181 R_SetupShader_SetPermutationGLSL(5, 8388608);
4182 R_SetupShader_SetPermutationGLSL(11, 1);
4183 R_SetupShader_SetPermutationGLSL(11, 2049);
4184 R_SetupShader_SetPermutationGLSL(11, 8193);
4185 R_SetupShader_SetPermutationGLSL(11, 10241);
4186 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4190 static void gl_main_shutdown(void)
4193 R_FrameData_Reset();
4194 R_BufferData_Reset();
4196 R_Main_FreeViewCache();
4198 switch(vid.renderpath)
4200 case RENDERPATH_GL11:
4201 case RENDERPATH_GL13:
4202 case RENDERPATH_GL20:
4203 case RENDERPATH_GLES1:
4204 case RENDERPATH_GLES2:
4205 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4207 qglDeleteQueriesARB(r_maxqueries, r_queries);
4210 case RENDERPATH_D3D9:
4211 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4213 case RENDERPATH_D3D10:
4214 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4216 case RENDERPATH_D3D11:
4217 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4219 case RENDERPATH_SOFT:
4225 memset(r_queries, 0, sizeof(r_queries));
4227 r_qwskincache = NULL;
4228 r_qwskincache_size = 0;
4230 // clear out the r_skinframe state
4231 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4232 memset(&r_skinframe, 0, sizeof(r_skinframe));
4235 Mem_Free(r_svbsp.nodes);
4236 memset(&r_svbsp, 0, sizeof (r_svbsp));
4237 R_FreeTexturePool(&r_main_texturepool);
4238 loadingscreentexture = NULL;
4239 r_texture_blanknormalmap = NULL;
4240 r_texture_white = NULL;
4241 r_texture_grey128 = NULL;
4242 r_texture_black = NULL;
4243 r_texture_whitecube = NULL;
4244 r_texture_normalizationcube = NULL;
4245 r_texture_fogattenuation = NULL;
4246 r_texture_fogheighttexture = NULL;
4247 r_texture_gammaramps = NULL;
4248 r_texture_numcubemaps = 0;
4249 //r_texture_fogintensity = NULL;
4250 memset(&r_fb, 0, sizeof(r_fb));
4253 r_glsl_permutation = NULL;
4254 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4255 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4256 glslshaderstring = NULL;
4258 r_hlsl_permutation = NULL;
4259 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4260 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4262 hlslshaderstring = NULL;
4265 static void gl_main_newmap(void)
4267 // FIXME: move this code to client
4268 char *entities, entname[MAX_QPATH];
4270 Mem_Free(r_qwskincache);
4271 r_qwskincache = NULL;
4272 r_qwskincache_size = 0;
4275 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4276 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4278 CL_ParseEntityLump(entities);
4282 if (cl.worldmodel->brush.entities)
4283 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4285 R_Main_FreeViewCache();
4287 R_FrameData_Reset();
4288 R_BufferData_Reset();
4291 void GL_Main_Init(void)
4294 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4296 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4297 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4298 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4299 if (gamemode == GAME_NEHAHRA)
4301 Cvar_RegisterVariable (&gl_fogenable);
4302 Cvar_RegisterVariable (&gl_fogdensity);
4303 Cvar_RegisterVariable (&gl_fogred);
4304 Cvar_RegisterVariable (&gl_foggreen);
4305 Cvar_RegisterVariable (&gl_fogblue);
4306 Cvar_RegisterVariable (&gl_fogstart);
4307 Cvar_RegisterVariable (&gl_fogend);
4308 Cvar_RegisterVariable (&gl_skyclip);
4310 Cvar_RegisterVariable(&r_motionblur);
4311 Cvar_RegisterVariable(&r_damageblur);
4312 Cvar_RegisterVariable(&r_motionblur_averaging);
4313 Cvar_RegisterVariable(&r_motionblur_randomize);
4314 Cvar_RegisterVariable(&r_motionblur_minblur);
4315 Cvar_RegisterVariable(&r_motionblur_maxblur);
4316 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4317 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4318 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4319 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4320 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4321 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4322 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4323 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4324 Cvar_RegisterVariable(&r_equalize_entities_by);
4325 Cvar_RegisterVariable(&r_equalize_entities_to);
4326 Cvar_RegisterVariable(&r_depthfirst);
4327 Cvar_RegisterVariable(&r_useinfinitefarclip);
4328 Cvar_RegisterVariable(&r_farclip_base);
4329 Cvar_RegisterVariable(&r_farclip_world);
4330 Cvar_RegisterVariable(&r_nearclip);
4331 Cvar_RegisterVariable(&r_deformvertexes);
4332 Cvar_RegisterVariable(&r_transparent);
4333 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4334 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4335 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4336 Cvar_RegisterVariable(&r_showoverdraw);
4337 Cvar_RegisterVariable(&r_showbboxes);
4338 Cvar_RegisterVariable(&r_showsurfaces);
4339 Cvar_RegisterVariable(&r_showtris);
4340 Cvar_RegisterVariable(&r_shownormals);
4341 Cvar_RegisterVariable(&r_showlighting);
4342 Cvar_RegisterVariable(&r_showshadowvolumes);
4343 Cvar_RegisterVariable(&r_showcollisionbrushes);
4344 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4345 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4346 Cvar_RegisterVariable(&r_showdisabledepthtest);
4347 Cvar_RegisterVariable(&r_drawportals);
4348 Cvar_RegisterVariable(&r_drawentities);
4349 Cvar_RegisterVariable(&r_draw2d);
4350 Cvar_RegisterVariable(&r_drawworld);
4351 Cvar_RegisterVariable(&r_cullentities_trace);
4352 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4353 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4354 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4355 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4356 Cvar_RegisterVariable(&r_sortentities);
4357 Cvar_RegisterVariable(&r_drawviewmodel);
4358 Cvar_RegisterVariable(&r_drawexteriormodel);
4359 Cvar_RegisterVariable(&r_speeds);
4360 Cvar_RegisterVariable(&r_fullbrights);
4361 Cvar_RegisterVariable(&r_wateralpha);
4362 Cvar_RegisterVariable(&r_dynamic);
4363 Cvar_RegisterVariable(&r_fakelight);
4364 Cvar_RegisterVariable(&r_fakelight_intensity);
4365 Cvar_RegisterVariable(&r_fullbright);
4366 Cvar_RegisterVariable(&r_shadows);
4367 Cvar_RegisterVariable(&r_shadows_darken);
4368 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4369 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4370 Cvar_RegisterVariable(&r_shadows_throwdistance);
4371 Cvar_RegisterVariable(&r_shadows_throwdirection);
4372 Cvar_RegisterVariable(&r_shadows_focus);
4373 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4374 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4375 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4376 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4377 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4378 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4379 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4380 Cvar_RegisterVariable(&r_fog_exp2);
4381 Cvar_RegisterVariable(&r_fog_clear);
4382 Cvar_RegisterVariable(&r_drawfog);
4383 Cvar_RegisterVariable(&r_transparentdepthmasking);
4384 Cvar_RegisterVariable(&r_transparent_sortmindist);
4385 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4386 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4387 Cvar_RegisterVariable(&r_texture_dds_load);
4388 Cvar_RegisterVariable(&r_texture_dds_save);
4389 Cvar_RegisterVariable(&r_textureunits);
4390 Cvar_RegisterVariable(&gl_combine);
4391 Cvar_RegisterVariable(&r_usedepthtextures);
4392 Cvar_RegisterVariable(&r_viewfbo);
4393 Cvar_RegisterVariable(&r_viewscale);
4394 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4395 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4396 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4397 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4398 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4399 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4400 Cvar_RegisterVariable(&r_glsl);
4401 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4402 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4403 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4404 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4405 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4406 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4407 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4408 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4409 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4410 Cvar_RegisterVariable(&r_glsl_postprocess);
4411 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4412 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4413 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4414 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4415 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4416 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4417 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4418 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4419 Cvar_RegisterVariable(&r_celshading);
4420 Cvar_RegisterVariable(&r_celoutlines);
4422 Cvar_RegisterVariable(&r_water);
4423 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4424 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4425 Cvar_RegisterVariable(&r_water_clippingplanebias);
4426 Cvar_RegisterVariable(&r_water_refractdistort);
4427 Cvar_RegisterVariable(&r_water_reflectdistort);
4428 Cvar_RegisterVariable(&r_water_scissormode);
4429 Cvar_RegisterVariable(&r_water_lowquality);
4430 Cvar_RegisterVariable(&r_water_hideplayer);
4431 Cvar_RegisterVariable(&r_water_fbo);
4433 Cvar_RegisterVariable(&r_lerpsprites);
4434 Cvar_RegisterVariable(&r_lerpmodels);
4435 Cvar_RegisterVariable(&r_lerplightstyles);
4436 Cvar_RegisterVariable(&r_waterscroll);
4437 Cvar_RegisterVariable(&r_bloom);
4438 Cvar_RegisterVariable(&r_bloom_colorscale);
4439 Cvar_RegisterVariable(&r_bloom_brighten);
4440 Cvar_RegisterVariable(&r_bloom_blur);
4441 Cvar_RegisterVariable(&r_bloom_resolution);
4442 Cvar_RegisterVariable(&r_bloom_colorexponent);
4443 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4444 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4445 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4446 Cvar_RegisterVariable(&r_hdr_glowintensity);
4447 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4448 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4449 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4450 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4451 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4452 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4453 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4454 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4455 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4456 Cvar_RegisterVariable(&developer_texturelogging);
4457 Cvar_RegisterVariable(&gl_lightmaps);
4458 Cvar_RegisterVariable(&r_test);
4459 Cvar_RegisterVariable(&r_batch_multidraw);
4460 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4461 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4462 Cvar_RegisterVariable(&r_glsl_skeletal);
4463 Cvar_RegisterVariable(&r_glsl_saturation);
4464 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4465 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4466 Cvar_RegisterVariable(&r_framedatasize);
4467 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4468 Cvar_RegisterVariable(&r_buffermegs[i]);
4469 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4470 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4471 Cvar_SetValue("r_fullbrights", 0);
4472 #ifdef DP_MOBILETOUCH
4473 // GLES devices have terrible depth precision in general, so...
4474 Cvar_SetValueQuick(&r_nearclip, 4);
4475 Cvar_SetValueQuick(&r_farclip_base, 4096);
4476 Cvar_SetValueQuick(&r_farclip_world, 0);
4477 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4479 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4482 void Render_Init(void)
4495 R_LightningBeams_Init();
4505 extern char *ENGINE_EXTENSIONS;
4508 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4509 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4510 gl_version = (const char *)qglGetString(GL_VERSION);
4511 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4515 if (!gl_platformextensions)
4516 gl_platformextensions = "";
4518 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4519 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4520 Con_Printf("GL_VERSION: %s\n", gl_version);
4521 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4522 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4524 VID_CheckExtensions();
4526 // LordHavoc: report supported extensions
4528 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4530 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4533 // clear to black (loading plaque will be seen over this)
4534 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4538 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4542 if (r_trippy.integer)
4544 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4546 p = r_refdef.view.frustum + i;
4551 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4555 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4559 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4563 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4567 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4571 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4575 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4579 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4587 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4591 if (r_trippy.integer)
4593 for (i = 0;i < numplanes;i++)
4600 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4604 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4608 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4612 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4616 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4620 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4624 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4628 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4636 //==================================================================================
4638 // LordHavoc: this stores temporary data used within the same frame
4640 typedef struct r_framedata_mem_s
4642 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4643 size_t size; // how much usable space
4644 size_t current; // how much space in use
4645 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4646 size_t wantedsize; // how much space was allocated
4647 unsigned char *data; // start of real data (16byte aligned)
4651 static r_framedata_mem_t *r_framedata_mem;
4653 void R_FrameData_Reset(void)
4655 while (r_framedata_mem)
4657 r_framedata_mem_t *next = r_framedata_mem->purge;
4658 Mem_Free(r_framedata_mem);
4659 r_framedata_mem = next;
4663 static void R_FrameData_Resize(qboolean mustgrow)
4666 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4667 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4668 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4670 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4671 newmem->wantedsize = wantedsize;
4672 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4673 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4674 newmem->current = 0;
4676 newmem->purge = r_framedata_mem;
4677 r_framedata_mem = newmem;
4681 void R_FrameData_NewFrame(void)
4683 R_FrameData_Resize(false);
4684 if (!r_framedata_mem)
4686 // if we ran out of space on the last frame, free the old memory now
4687 while (r_framedata_mem->purge)
4689 // repeatedly remove the second item in the list, leaving only head
4690 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4691 Mem_Free(r_framedata_mem->purge);
4692 r_framedata_mem->purge = next;
4694 // reset the current mem pointer
4695 r_framedata_mem->current = 0;
4696 r_framedata_mem->mark = 0;
4699 void *R_FrameData_Alloc(size_t size)
4704 // align to 16 byte boundary - the data pointer is already aligned, so we
4705 // only need to ensure the size of every allocation is also aligned
4706 size = (size + 15) & ~15;
4708 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4710 // emergency - we ran out of space, allocate more memory
4711 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4712 // this might not be a growing it, but we'll allocate another buffer every time
4713 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4714 R_FrameData_Resize(true);
4717 data = r_framedata_mem->data + r_framedata_mem->current;
4718 r_framedata_mem->current += size;
4720 // count the usage for stats
4721 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4722 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4724 return (void *)data;
4727 void *R_FrameData_Store(size_t size, void *data)
4729 void *d = R_FrameData_Alloc(size);
4731 memcpy(d, data, size);
4735 void R_FrameData_SetMark(void)
4737 if (!r_framedata_mem)
4739 r_framedata_mem->mark = r_framedata_mem->current;
4742 void R_FrameData_ReturnToMark(void)
4744 if (!r_framedata_mem)
4746 r_framedata_mem->current = r_framedata_mem->mark;
4749 //==================================================================================
4751 // avoid reusing the same buffer objects on consecutive frames
4752 #define R_BUFFERDATA_CYCLE 3
4754 typedef struct r_bufferdata_buffer_s
4756 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4757 size_t size; // how much usable space
4758 size_t current; // how much space in use
4759 r_meshbuffer_t *buffer; // the buffer itself
4761 r_bufferdata_buffer_t;
4763 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4764 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4766 /// frees all dynamic buffers
4767 void R_BufferData_Reset(void)
4770 r_bufferdata_buffer_t **p, *mem;
4771 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4773 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4776 p = &r_bufferdata_buffer[cycle][type];
4782 R_Mesh_DestroyMeshBuffer(mem->buffer);
4789 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4790 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4792 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4794 float newvalue = r_buffermegs[type].value;
4796 // increase the cvar if we have to (but only if we already have a mem)
4797 if (mustgrow && mem)
4799 newvalue = bound(0.25f, newvalue, 256.0f);
4800 while (newvalue * 1024*1024 < minsize)
4803 // clamp the cvar to valid range
4804 newvalue = bound(0.25f, newvalue, 256.0f);
4805 if (r_buffermegs[type].value != newvalue)
4806 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4808 // calculate size in bytes
4809 size = (size_t)(newvalue * 1024*1024);
4810 size = bound(131072, size, 256*1024*1024);
4812 // allocate a new buffer if the size is different (purge old one later)
4813 // or if we were told we must grow the buffer
4814 if (!mem || mem->size != size || mustgrow)
4816 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4819 if (type == R_BUFFERDATA_VERTEX)
4820 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4821 else if (type == R_BUFFERDATA_INDEX16)
4822 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4823 else if (type == R_BUFFERDATA_INDEX32)
4824 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4825 else if (type == R_BUFFERDATA_UNIFORM)
4826 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4827 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4828 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4832 void R_BufferData_NewFrame(void)
4835 r_bufferdata_buffer_t **p, *mem;
4836 // cycle to the next frame's buffers
4837 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4838 // if we ran out of space on the last time we used these buffers, free the old memory now
4839 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4841 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4843 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4844 // free all but the head buffer, this is how we recycle obsolete
4845 // buffers after they are no longer in use
4846 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4852 R_Mesh_DestroyMeshBuffer(mem->buffer);
4855 // reset the current offset
4856 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4861 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4863 r_bufferdata_buffer_t *mem;
4867 *returnbufferoffset = 0;
4869 // align size to a byte boundary appropriate for the buffer type, this
4870 // makes all allocations have aligned start offsets
4871 if (type == R_BUFFERDATA_UNIFORM)
4872 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4874 padsize = (datasize + 15) & ~15;
4876 // if we ran out of space in this buffer we must allocate a new one
4877 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)
4878 R_BufferData_Resize(type, true, padsize);
4880 // if the resize did not give us enough memory, fail
4881 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)
4882 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4884 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4885 offset = (int)mem->current;
4886 mem->current += padsize;
4888 // upload the data to the buffer at the chosen offset
4890 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4891 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4893 // count the usage for stats
4894 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4895 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4897 // return the buffer offset
4898 *returnbufferoffset = offset;
4903 //==================================================================================
4905 // LordHavoc: animcache originally written by Echon, rewritten since then
4908 * Animation cache prevents re-generating mesh data for an animated model
4909 * multiple times in one frame for lighting, shadowing, reflections, etc.
4912 void R_AnimCache_Free(void)
4916 void R_AnimCache_ClearCache(void)
4919 entity_render_t *ent;
4921 for (i = 0;i < r_refdef.scene.numentities;i++)
4923 ent = r_refdef.scene.entities[i];
4924 ent->animcache_vertex3f = NULL;
4925 ent->animcache_vertex3f_vertexbuffer = NULL;
4926 ent->animcache_vertex3f_bufferoffset = 0;
4927 ent->animcache_normal3f = NULL;
4928 ent->animcache_normal3f_vertexbuffer = NULL;
4929 ent->animcache_normal3f_bufferoffset = 0;
4930 ent->animcache_svector3f = NULL;
4931 ent->animcache_svector3f_vertexbuffer = NULL;
4932 ent->animcache_svector3f_bufferoffset = 0;
4933 ent->animcache_tvector3f = NULL;
4934 ent->animcache_tvector3f_vertexbuffer = NULL;
4935 ent->animcache_tvector3f_bufferoffset = 0;
4936 ent->animcache_vertexmesh = NULL;
4937 ent->animcache_vertexmesh_vertexbuffer = NULL;
4938 ent->animcache_vertexmesh_bufferoffset = 0;
4939 ent->animcache_skeletaltransform3x4 = NULL;
4940 ent->animcache_skeletaltransform3x4buffer = NULL;
4941 ent->animcache_skeletaltransform3x4offset = 0;
4942 ent->animcache_skeletaltransform3x4size = 0;
4946 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4950 // check if we need the meshbuffers
4951 if (!vid.useinterleavedarrays)
4954 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4955 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4956 // TODO: upload vertexbuffer?
4957 if (ent->animcache_vertexmesh)
4959 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4960 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4961 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4962 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4963 for (i = 0;i < numvertices;i++)
4964 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4965 if (ent->animcache_svector3f)
4966 for (i = 0;i < numvertices;i++)
4967 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4968 if (ent->animcache_tvector3f)
4969 for (i = 0;i < numvertices;i++)
4970 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4971 if (ent->animcache_normal3f)
4972 for (i = 0;i < numvertices;i++)
4973 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4977 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4979 dp_model_t *model = ent->model;
4982 // see if this ent is worth caching
4983 if (!model || !model->Draw || !model->AnimateVertices)
4985 // nothing to cache if it contains no animations and has no skeleton
4986 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4988 // see if it is already cached for gpuskeletal
4989 if (ent->animcache_skeletaltransform3x4)
4991 // see if it is already cached as a mesh
4992 if (ent->animcache_vertex3f)
4994 // check if we need to add normals or tangents
4995 if (ent->animcache_normal3f)
4996 wantnormals = false;
4997 if (ent->animcache_svector3f)
4998 wanttangents = false;
4999 if (!wantnormals && !wanttangents)
5003 // check which kind of cache we need to generate
5004 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5006 // cache the skeleton so the vertex shader can use it
5007 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5008 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5009 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5010 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5011 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
5012 // note: this can fail if the buffer is at the grow limit
5013 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5014 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5016 else if (ent->animcache_vertex3f)
5018 // mesh was already cached but we may need to add normals/tangents
5019 // (this only happens with multiple views, reflections, cameras, etc)
5020 if (wantnormals || wanttangents)
5022 numvertices = model->surfmesh.num_vertices;
5024 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5027 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5028 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5030 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5031 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5032 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5033 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5034 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5039 // generate mesh cache
5040 numvertices = model->surfmesh.num_vertices;
5041 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5043 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5046 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5047 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5049 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5050 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5051 if (wantnormals || wanttangents)
5053 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5054 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5055 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5057 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5058 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5059 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5064 void R_AnimCache_CacheVisibleEntities(void)
5067 qboolean wantnormals = true;
5068 qboolean wanttangents = !r_showsurfaces.integer;
5070 switch(vid.renderpath)
5072 case RENDERPATH_GL20:
5073 case RENDERPATH_D3D9:
5074 case RENDERPATH_D3D10:
5075 case RENDERPATH_D3D11:
5076 case RENDERPATH_GLES2:
5078 case RENDERPATH_GL11:
5079 case RENDERPATH_GL13:
5080 case RENDERPATH_GLES1:
5081 wanttangents = false;
5083 case RENDERPATH_SOFT:
5087 if (r_shownormals.integer)
5088 wanttangents = wantnormals = true;
5090 // TODO: thread this
5091 // NOTE: R_PrepareRTLights() also caches entities
5093 for (i = 0;i < r_refdef.scene.numentities;i++)
5094 if (r_refdef.viewcache.entityvisible[i])
5095 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5098 //==================================================================================
5100 extern cvar_t r_overheadsprites_pushback;
5102 static void R_View_UpdateEntityLighting (void)
5105 entity_render_t *ent;
5106 vec3_t tempdiffusenormal, avg;
5107 vec_t f, fa, fd, fdd;
5108 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5110 for (i = 0;i < r_refdef.scene.numentities;i++)
5112 ent = r_refdef.scene.entities[i];
5114 // skip unseen models
5115 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5119 if (ent->model && ent->model == cl.worldmodel)
5121 // TODO: use modellight for r_ambient settings on world?
5122 VectorSet(ent->modellight_ambient, 0, 0, 0);
5123 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5124 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5128 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5130 // aleady updated by CSQC
5131 // TODO: force modellight on BSP models in this case?
5132 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5136 // fetch the lighting from the worldmodel data
5137 VectorClear(ent->modellight_ambient);
5138 VectorClear(ent->modellight_diffuse);
5139 VectorClear(tempdiffusenormal);
5140 if (ent->flags & RENDER_LIGHT)
5143 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5145 // complete lightning for lit sprites
5146 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5147 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5149 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5150 org[2] = org[2] + r_overheadsprites_pushback.value;
5151 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5154 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5156 if(ent->flags & RENDER_EQUALIZE)
5158 // first fix up ambient lighting...
5159 if(r_equalize_entities_minambient.value > 0)
5161 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5164 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5165 if(fa < r_equalize_entities_minambient.value * fd)
5168 // fa'/fd' = minambient
5169 // fa'+0.25*fd' = fa+0.25*fd
5171 // fa' = fd' * minambient
5172 // fd'*(0.25+minambient) = fa+0.25*fd
5174 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5175 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5177 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5178 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
5179 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5180 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5185 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5187 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5188 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5192 // adjust brightness and saturation to target
5193 avg[0] = avg[1] = avg[2] = fa / f;
5194 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5195 avg[0] = avg[1] = avg[2] = fd / f;
5196 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5202 VectorSet(ent->modellight_ambient, 1, 1, 1);
5205 // move the light direction into modelspace coordinates for lighting code
5206 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5207 if(VectorLength2(ent->modellight_lightdir) == 0)
5208 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5209 VectorNormalize(ent->modellight_lightdir);
5213 #define MAX_LINEOFSIGHTTRACES 64
5215 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5218 vec3_t boxmins, boxmaxs;
5221 dp_model_t *model = r_refdef.scene.worldmodel;
5223 if (!model || !model->brush.TraceLineOfSight)
5226 // expand the box a little
5227 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5228 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5229 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5230 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5231 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5232 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5234 // return true if eye is inside enlarged box
5235 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5239 VectorCopy(eye, start);
5240 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5241 if (model->brush.TraceLineOfSight(model, start, end))
5244 // try various random positions
5245 for (i = 0;i < numsamples;i++)
5247 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5248 if (model->brush.TraceLineOfSight(model, start, end))
5256 static void R_View_UpdateEntityVisible (void)
5261 entity_render_t *ent;
5263 if (r_refdef.envmap || r_fb.water.hideplayer)
5264 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5265 else if (chase_active.integer || r_fb.water.renderingscene)
5266 renderimask = RENDER_VIEWMODEL;
5268 renderimask = RENDER_EXTERIORMODEL;
5269 if (!r_drawviewmodel.integer)
5270 renderimask |= RENDER_VIEWMODEL;
5271 if (!r_drawexteriormodel.integer)
5272 renderimask |= RENDER_EXTERIORMODEL;
5273 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5274 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5276 // worldmodel can check visibility
5277 for (i = 0;i < r_refdef.scene.numentities;i++)
5279 ent = r_refdef.scene.entities[i];
5280 if (!(ent->flags & renderimask))
5281 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)))
5282 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))
5283 r_refdef.viewcache.entityvisible[i] = true;
5288 // no worldmodel or it can't check visibility
5289 for (i = 0;i < r_refdef.scene.numentities;i++)
5291 ent = r_refdef.scene.entities[i];
5292 if (!(ent->flags & renderimask))
5293 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)))
5294 r_refdef.viewcache.entityvisible[i] = true;
5297 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5298 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5300 for (i = 0;i < r_refdef.scene.numentities;i++)
5302 if (!r_refdef.viewcache.entityvisible[i])
5304 ent = r_refdef.scene.entities[i];
5305 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5307 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5309 continue; // temp entities do pvs only
5310 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5311 ent->last_trace_visibility = realtime;
5312 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5313 r_refdef.viewcache.entityvisible[i] = 0;
5319 /// only used if skyrendermasked, and normally returns false
5320 static int R_DrawBrushModelsSky (void)
5323 entity_render_t *ent;
5326 for (i = 0;i < r_refdef.scene.numentities;i++)
5328 if (!r_refdef.viewcache.entityvisible[i])
5330 ent = r_refdef.scene.entities[i];
5331 if (!ent->model || !ent->model->DrawSky)
5333 ent->model->DrawSky(ent);
5339 static void R_DrawNoModel(entity_render_t *ent);
5340 static void R_DrawModels(void)
5343 entity_render_t *ent;
5345 for (i = 0;i < r_refdef.scene.numentities;i++)
5347 if (!r_refdef.viewcache.entityvisible[i])
5349 ent = r_refdef.scene.entities[i];
5350 r_refdef.stats[r_stat_entities]++;
5352 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5355 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5356 Con_Printf("R_DrawModels\n");
5357 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]);
5358 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);
5359 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);
5362 if (ent->model && ent->model->Draw != NULL)
5363 ent->model->Draw(ent);
5369 static void R_DrawModelsDepth(void)
5372 entity_render_t *ent;
5374 for (i = 0;i < r_refdef.scene.numentities;i++)
5376 if (!r_refdef.viewcache.entityvisible[i])
5378 ent = r_refdef.scene.entities[i];
5379 if (ent->model && ent->model->DrawDepth != NULL)
5380 ent->model->DrawDepth(ent);
5384 static void R_DrawModelsDebug(void)
5387 entity_render_t *ent;
5389 for (i = 0;i < r_refdef.scene.numentities;i++)
5391 if (!r_refdef.viewcache.entityvisible[i])
5393 ent = r_refdef.scene.entities[i];
5394 if (ent->model && ent->model->DrawDebug != NULL)
5395 ent->model->DrawDebug(ent);
5399 static void R_DrawModelsAddWaterPlanes(void)
5402 entity_render_t *ent;
5404 for (i = 0;i < r_refdef.scene.numentities;i++)
5406 if (!r_refdef.viewcache.entityvisible[i])
5408 ent = r_refdef.scene.entities[i];
5409 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5410 ent->model->DrawAddWaterPlanes(ent);
5414 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}};
5416 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5418 if (r_hdr_irisadaptation.integer)
5423 vec3_t diffusenormal;
5425 vec_t brightness = 0.0f;
5430 VectorCopy(r_refdef.view.forward, forward);
5431 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5433 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5434 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5435 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5436 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5437 d = DotProduct(forward, diffusenormal);
5438 brightness += VectorLength(ambient);
5440 brightness += d * VectorLength(diffuse);
5442 brightness *= 1.0f / c;
5443 brightness += 0.00001f; // make sure it's never zero
5444 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5445 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5446 current = r_hdr_irisadaptation_value.value;
5448 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5449 else if (current > goal)
5450 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5451 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5452 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5454 else if (r_hdr_irisadaptation_value.value != 1.0f)
5455 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5458 static void R_View_SetFrustum(const int *scissor)
5461 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5462 vec3_t forward, left, up, origin, v;
5466 // flipped x coordinates (because x points left here)
5467 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5468 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5470 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5471 switch(vid.renderpath)
5473 case RENDERPATH_D3D9:
5474 case RENDERPATH_D3D10:
5475 case RENDERPATH_D3D11:
5476 // non-flipped y coordinates
5477 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5478 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5480 case RENDERPATH_SOFT:
5481 case RENDERPATH_GL11:
5482 case RENDERPATH_GL13:
5483 case RENDERPATH_GL20:
5484 case RENDERPATH_GLES1:
5485 case RENDERPATH_GLES2:
5486 // non-flipped y coordinates
5487 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5488 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5493 // we can't trust r_refdef.view.forward and friends in reflected scenes
5494 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5497 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5498 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5499 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5500 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5501 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5502 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5503 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5504 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5505 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5506 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5507 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5508 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5512 zNear = r_refdef.nearclip;
5513 nudge = 1.0 - 1.0 / (1<<23);
5514 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5515 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5516 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5517 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5518 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5519 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5520 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5521 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5527 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5528 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5529 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5530 r_refdef.view.frustum[0].dist = m[15] - m[12];
5532 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5533 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5534 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5535 r_refdef.view.frustum[1].dist = m[15] + m[12];
5537 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5538 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5539 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5540 r_refdef.view.frustum[2].dist = m[15] - m[13];
5542 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5543 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5544 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5545 r_refdef.view.frustum[3].dist = m[15] + m[13];
5547 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5548 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5549 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5550 r_refdef.view.frustum[4].dist = m[15] - m[14];
5552 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5553 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5554 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5555 r_refdef.view.frustum[5].dist = m[15] + m[14];
5558 if (r_refdef.view.useperspective)
5560 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5561 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]);
5562 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]);
5563 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]);
5564 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]);
5566 // then the normals from the corners relative to origin
5567 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5568 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5569 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5570 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5572 // in a NORMAL view, forward cross left == up
5573 // in a REFLECTED view, forward cross left == down
5574 // so our cross products above need to be adjusted for a left handed coordinate system
5575 CrossProduct(forward, left, v);
5576 if(DotProduct(v, up) < 0)
5578 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5579 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5580 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5581 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5584 // Leaving those out was a mistake, those were in the old code, and they
5585 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5586 // I couldn't reproduce it after adding those normalizations. --blub
5587 VectorNormalize(r_refdef.view.frustum[0].normal);
5588 VectorNormalize(r_refdef.view.frustum[1].normal);
5589 VectorNormalize(r_refdef.view.frustum[2].normal);
5590 VectorNormalize(r_refdef.view.frustum[3].normal);
5592 // make the corners absolute
5593 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5594 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5595 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5596 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5599 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5601 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5602 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5603 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5604 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5605 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5609 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5610 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5611 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5612 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5613 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5614 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5615 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5616 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5617 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5618 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5620 r_refdef.view.numfrustumplanes = 5;
5622 if (r_refdef.view.useclipplane)
5624 r_refdef.view.numfrustumplanes = 6;
5625 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5628 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5629 PlaneClassify(r_refdef.view.frustum + i);
5631 // LordHavoc: note to all quake engine coders, Quake had a special case
5632 // for 90 degrees which assumed a square view (wrong), so I removed it,
5633 // Quake2 has it disabled as well.
5635 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5636 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5637 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5638 //PlaneClassify(&frustum[0]);
5640 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5641 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5642 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5643 //PlaneClassify(&frustum[1]);
5645 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5646 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5647 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5648 //PlaneClassify(&frustum[2]);
5650 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5651 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5652 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5653 //PlaneClassify(&frustum[3]);
5656 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5657 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5658 //PlaneClassify(&frustum[4]);
5661 static void R_View_UpdateWithScissor(const int *myscissor)
5663 R_Main_ResizeViewCache();
5664 R_View_SetFrustum(myscissor);
5665 R_View_WorldVisibility(r_refdef.view.useclipplane);
5666 R_View_UpdateEntityVisible();
5667 R_View_UpdateEntityLighting();
5670 static void R_View_Update(void)
5672 R_Main_ResizeViewCache();
5673 R_View_SetFrustum(NULL);
5674 R_View_WorldVisibility(r_refdef.view.useclipplane);
5675 R_View_UpdateEntityVisible();
5676 R_View_UpdateEntityLighting();
5679 float viewscalefpsadjusted = 1.0f;
5681 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5683 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5684 scale = bound(0.03125f, scale, 1.0f);
5685 *outwidth = (int)ceil(width * scale);
5686 *outheight = (int)ceil(height * scale);
5689 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5691 const float *customclipplane = NULL;
5693 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5694 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5696 // LordHavoc: couldn't figure out how to make this approach the
5697 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5698 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5699 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5700 dist = r_refdef.view.clipplane.dist;
5701 plane[0] = r_refdef.view.clipplane.normal[0];
5702 plane[1] = r_refdef.view.clipplane.normal[1];
5703 plane[2] = r_refdef.view.clipplane.normal[2];
5705 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5708 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5709 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5711 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5712 if (!r_refdef.view.useperspective)
5713 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);
5714 else if (vid.stencil && r_useinfinitefarclip.integer)
5715 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);
5717 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);
5718 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5719 R_SetViewport(&r_refdef.view.viewport);
5720 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5722 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5723 float screenplane[4];
5724 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5725 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5726 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5727 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5728 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5732 void R_EntityMatrix(const matrix4x4_t *matrix)
5734 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5736 gl_modelmatrixchanged = false;
5737 gl_modelmatrix = *matrix;
5738 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5739 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5740 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5741 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5743 switch(vid.renderpath)
5745 case RENDERPATH_D3D9:
5747 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5748 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5751 case RENDERPATH_D3D10:
5752 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5754 case RENDERPATH_D3D11:
5755 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5757 case RENDERPATH_GL11:
5758 case RENDERPATH_GL13:
5759 case RENDERPATH_GLES1:
5761 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5764 case RENDERPATH_SOFT:
5765 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5766 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5768 case RENDERPATH_GL20:
5769 case RENDERPATH_GLES2:
5770 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5771 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5777 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5779 r_viewport_t viewport;
5783 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5784 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);
5785 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5786 R_SetViewport(&viewport);
5787 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5788 GL_Color(1, 1, 1, 1);
5789 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5790 GL_BlendFunc(GL_ONE, GL_ZERO);
5791 GL_ScissorTest(false);
5792 GL_DepthMask(false);
5793 GL_DepthRange(0, 1);
5794 GL_DepthTest(false);
5795 GL_DepthFunc(GL_LEQUAL);
5796 R_EntityMatrix(&identitymatrix);
5797 R_Mesh_ResetTextureState();
5798 GL_PolygonOffset(0, 0);
5799 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5800 switch(vid.renderpath)
5802 case RENDERPATH_GL11:
5803 case RENDERPATH_GL13:
5804 case RENDERPATH_GL20:
5805 case RENDERPATH_GLES1:
5806 case RENDERPATH_GLES2:
5807 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5809 case RENDERPATH_D3D9:
5810 case RENDERPATH_D3D10:
5811 case RENDERPATH_D3D11:
5812 case RENDERPATH_SOFT:
5815 GL_CullFace(GL_NONE);
5820 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5824 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5827 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5831 R_SetupView(true, fbo, depthtexture, colortexture);
5832 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5833 GL_Color(1, 1, 1, 1);
5834 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5835 GL_BlendFunc(GL_ONE, GL_ZERO);
5836 GL_ScissorTest(true);
5838 GL_DepthRange(0, 1);
5840 GL_DepthFunc(GL_LEQUAL);
5841 R_EntityMatrix(&identitymatrix);
5842 R_Mesh_ResetTextureState();
5843 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5844 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5845 switch(vid.renderpath)
5847 case RENDERPATH_GL11:
5848 case RENDERPATH_GL13:
5849 case RENDERPATH_GL20:
5850 case RENDERPATH_GLES1:
5851 case RENDERPATH_GLES2:
5852 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5854 case RENDERPATH_D3D9:
5855 case RENDERPATH_D3D10:
5856 case RENDERPATH_D3D11:
5857 case RENDERPATH_SOFT:
5860 GL_CullFace(r_refdef.view.cullface_back);
5865 R_RenderView_UpdateViewVectors
5868 void R_RenderView_UpdateViewVectors(void)
5870 // break apart the view matrix into vectors for various purposes
5871 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5872 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5873 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5874 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5875 // make an inverted copy of the view matrix for tracking sprites
5876 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5879 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5880 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5882 static void R_Water_StartFrame(void)
5885 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5886 r_waterstate_waterplane_t *p;
5887 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;
5889 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5892 switch(vid.renderpath)
5894 case RENDERPATH_GL20:
5895 case RENDERPATH_D3D9:
5896 case RENDERPATH_D3D10:
5897 case RENDERPATH_D3D11:
5898 case RENDERPATH_SOFT:
5899 case RENDERPATH_GLES2:
5901 case RENDERPATH_GL11:
5902 case RENDERPATH_GL13:
5903 case RENDERPATH_GLES1:
5907 // set waterwidth and waterheight to the water resolution that will be
5908 // used (often less than the screen resolution for faster rendering)
5909 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5911 // calculate desired texture sizes
5912 // can't use water if the card does not support the texture size
5913 if (!r_water.integer || r_showsurfaces.integer)
5914 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5915 else if (vid.support.arb_texture_non_power_of_two)
5917 texturewidth = waterwidth;
5918 textureheight = waterheight;
5919 camerawidth = waterwidth;
5920 cameraheight = waterheight;
5924 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5925 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5926 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5927 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5930 // allocate textures as needed
5931 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))
5933 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5934 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5936 if (p->texture_refraction)
5937 R_FreeTexture(p->texture_refraction);
5938 p->texture_refraction = NULL;
5939 if (p->fbo_refraction)
5940 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5941 p->fbo_refraction = 0;
5942 if (p->texture_reflection)
5943 R_FreeTexture(p->texture_reflection);
5944 p->texture_reflection = NULL;
5945 if (p->fbo_reflection)
5946 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5947 p->fbo_reflection = 0;
5948 if (p->texture_camera)
5949 R_FreeTexture(p->texture_camera);
5950 p->texture_camera = NULL;
5952 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5955 memset(&r_fb.water, 0, sizeof(r_fb.water));
5956 r_fb.water.texturewidth = texturewidth;
5957 r_fb.water.textureheight = textureheight;
5958 r_fb.water.camerawidth = camerawidth;
5959 r_fb.water.cameraheight = cameraheight;
5962 if (r_fb.water.texturewidth)
5964 int scaledwidth, scaledheight;
5966 r_fb.water.enabled = true;
5968 // water resolution is usually reduced
5969 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5970 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5971 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5973 // set up variables that will be used in shader setup
5974 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5975 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5976 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5977 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5980 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5981 r_fb.water.numwaterplanes = 0;
5984 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5986 int planeindex, bestplaneindex, vertexindex;
5987 vec3_t mins, maxs, normal, center, v, n;
5988 vec_t planescore, bestplanescore;
5990 r_waterstate_waterplane_t *p;
5991 texture_t *t = R_GetCurrentTexture(surface->texture);
5993 rsurface.texture = t;
5994 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5995 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5996 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5998 // average the vertex normals, find the surface bounds (after deformvertexes)
5999 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6000 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6001 VectorCopy(n, normal);
6002 VectorCopy(v, mins);
6003 VectorCopy(v, maxs);
6004 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6006 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6007 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6008 VectorAdd(normal, n, normal);
6009 mins[0] = min(mins[0], v[0]);
6010 mins[1] = min(mins[1], v[1]);
6011 mins[2] = min(mins[2], v[2]);
6012 maxs[0] = max(maxs[0], v[0]);
6013 maxs[1] = max(maxs[1], v[1]);
6014 maxs[2] = max(maxs[2], v[2]);
6016 VectorNormalize(normal);
6017 VectorMAM(0.5f, mins, 0.5f, maxs, center);
6019 VectorCopy(normal, plane.normal);
6020 VectorNormalize(plane.normal);
6021 plane.dist = DotProduct(center, plane.normal);
6022 PlaneClassify(&plane);
6023 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6025 // skip backfaces (except if nocullface is set)
6026 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6028 VectorNegate(plane.normal, plane.normal);
6030 PlaneClassify(&plane);
6034 // find a matching plane if there is one
6035 bestplaneindex = -1;
6036 bestplanescore = 1048576.0f;
6037 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6039 if(p->camera_entity == t->camera_entity)
6041 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6042 if (bestplaneindex < 0 || bestplanescore > planescore)
6044 bestplaneindex = planeindex;
6045 bestplanescore = planescore;
6049 planeindex = bestplaneindex;
6051 // if this surface does not fit any known plane rendered this frame, add one
6052 if (planeindex < 0 || bestplanescore > 0.001f)
6054 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6056 // store the new plane
6057 planeindex = r_fb.water.numwaterplanes++;
6058 p = r_fb.water.waterplanes + planeindex;
6060 // clear materialflags and pvs
6061 p->materialflags = 0;
6062 p->pvsvalid = false;
6063 p->camera_entity = t->camera_entity;
6064 VectorCopy(mins, p->mins);
6065 VectorCopy(maxs, p->maxs);
6069 // We're totally screwed.
6075 // merge mins/maxs when we're adding this surface to the plane
6076 p = r_fb.water.waterplanes + planeindex;
6077 p->mins[0] = min(p->mins[0], mins[0]);
6078 p->mins[1] = min(p->mins[1], mins[1]);
6079 p->mins[2] = min(p->mins[2], mins[2]);
6080 p->maxs[0] = max(p->maxs[0], maxs[0]);
6081 p->maxs[1] = max(p->maxs[1], maxs[1]);
6082 p->maxs[2] = max(p->maxs[2], maxs[2]);
6084 // merge this surface's materialflags into the waterplane
6085 p->materialflags |= t->currentmaterialflags;
6086 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6088 // merge this surface's PVS into the waterplane
6089 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6090 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6092 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6098 extern cvar_t r_drawparticles;
6099 extern cvar_t r_drawdecals;
6101 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6104 r_refdef_view_t originalview;
6105 r_refdef_view_t myview;
6106 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;
6107 r_waterstate_waterplane_t *p;
6109 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;
6112 originalview = r_refdef.view;
6114 // lowquality hack, temporarily shut down some cvars and restore afterwards
6115 qualityreduction = r_water_lowquality.integer;
6116 if (qualityreduction > 0)
6118 if (qualityreduction >= 1)
6120 old_r_shadows = r_shadows.integer;
6121 old_r_worldrtlight = r_shadow_realtime_world.integer;
6122 old_r_dlight = r_shadow_realtime_dlight.integer;
6123 Cvar_SetValueQuick(&r_shadows, 0);
6124 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6125 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6127 if (qualityreduction >= 2)
6129 old_r_dynamic = r_dynamic.integer;
6130 old_r_particles = r_drawparticles.integer;
6131 old_r_decals = r_drawdecals.integer;
6132 Cvar_SetValueQuick(&r_dynamic, 0);
6133 Cvar_SetValueQuick(&r_drawparticles, 0);
6134 Cvar_SetValueQuick(&r_drawdecals, 0);
6138 // make sure enough textures are allocated
6139 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6141 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6143 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6145 if (!p->texture_refraction)
6146 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);
6147 if (!p->texture_refraction)
6151 if (r_fb.water.depthtexture == NULL)
6152 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6153 if (p->fbo_refraction == 0)
6154 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6157 else if (p->materialflags & MATERIALFLAG_CAMERA)
6159 if (!p->texture_camera)
6160 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);
6161 if (!p->texture_camera)
6165 if (r_fb.water.depthtexture == NULL)
6166 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6167 if (p->fbo_camera == 0)
6168 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6172 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6174 if (!p->texture_reflection)
6175 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);
6176 if (!p->texture_reflection)
6180 if (r_fb.water.depthtexture == NULL)
6181 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6182 if (p->fbo_reflection == 0)
6183 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6189 r_refdef.view = originalview;
6190 r_refdef.view.showdebug = false;
6191 r_refdef.view.width = r_fb.water.waterwidth;
6192 r_refdef.view.height = r_fb.water.waterheight;
6193 r_refdef.view.useclipplane = true;
6194 myview = r_refdef.view;
6195 r_fb.water.renderingscene = true;
6196 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6198 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6200 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6202 r_refdef.view = myview;
6203 if(r_water_scissormode.integer)
6205 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6206 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6207 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6210 // render reflected scene and copy into texture
6211 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6212 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6213 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6214 r_refdef.view.clipplane = p->plane;
6215 // reverse the cullface settings for this render
6216 r_refdef.view.cullface_front = GL_FRONT;
6217 r_refdef.view.cullface_back = GL_BACK;
6218 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6220 r_refdef.view.usecustompvs = true;
6222 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6224 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6227 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6228 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6229 R_ClearScreen(r_refdef.fogenabled);
6230 if(r_water_scissormode.integer & 2)
6231 R_View_UpdateWithScissor(myscissor);
6234 R_AnimCache_CacheVisibleEntities();
6235 if(r_water_scissormode.integer & 1)
6236 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6237 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6239 if (!p->fbo_reflection)
6240 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);
6241 r_fb.water.hideplayer = false;
6244 // render the normal view scene and copy into texture
6245 // (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)
6246 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6248 r_refdef.view = myview;
6249 if(r_water_scissormode.integer)
6251 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6252 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6253 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6256 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6258 r_refdef.view.clipplane = p->plane;
6259 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6260 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6262 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6264 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6265 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6266 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6267 R_RenderView_UpdateViewVectors();
6268 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6270 r_refdef.view.usecustompvs = true;
6271 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);
6275 PlaneClassify(&r_refdef.view.clipplane);
6277 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6278 R_ClearScreen(r_refdef.fogenabled);
6279 if(r_water_scissormode.integer & 2)
6280 R_View_UpdateWithScissor(myscissor);
6283 R_AnimCache_CacheVisibleEntities();
6284 if(r_water_scissormode.integer & 1)
6285 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6286 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6288 if (!p->fbo_refraction)
6289 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);
6290 r_fb.water.hideplayer = false;
6292 else if (p->materialflags & MATERIALFLAG_CAMERA)
6294 r_refdef.view = myview;
6296 r_refdef.view.clipplane = p->plane;
6297 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6298 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6300 r_refdef.view.width = r_fb.water.camerawidth;
6301 r_refdef.view.height = r_fb.water.cameraheight;
6302 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6303 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6304 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6305 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6307 if(p->camera_entity)
6309 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6310 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6313 // note: all of the view is used for displaying... so
6314 // there is no use in scissoring
6316 // reverse the cullface settings for this render
6317 r_refdef.view.cullface_front = GL_FRONT;
6318 r_refdef.view.cullface_back = GL_BACK;
6319 // also reverse the view matrix
6320 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
6321 R_RenderView_UpdateViewVectors();
6322 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6324 r_refdef.view.usecustompvs = true;
6325 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);
6328 // camera needs no clipplane
6329 r_refdef.view.useclipplane = false;
6331 PlaneClassify(&r_refdef.view.clipplane);
6333 r_fb.water.hideplayer = false;
6335 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6336 R_ClearScreen(r_refdef.fogenabled);
6338 R_AnimCache_CacheVisibleEntities();
6339 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6342 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);
6343 r_fb.water.hideplayer = false;
6347 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6348 r_fb.water.renderingscene = false;
6349 r_refdef.view = originalview;
6350 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6351 if (!r_fb.water.depthtexture)
6352 R_ClearScreen(r_refdef.fogenabled);
6354 R_AnimCache_CacheVisibleEntities();
6357 r_refdef.view = originalview;
6358 r_fb.water.renderingscene = false;
6359 Cvar_SetValueQuick(&r_water, 0);
6360 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6362 // lowquality hack, restore cvars
6363 if (qualityreduction > 0)
6365 if (qualityreduction >= 1)
6367 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6368 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6369 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6371 if (qualityreduction >= 2)
6373 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6374 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6375 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6380 static void R_Bloom_StartFrame(void)
6383 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6384 int viewwidth, viewheight;
6385 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6386 textype_t textype = TEXTYPE_COLORBUFFER;
6388 switch (vid.renderpath)
6390 case RENDERPATH_GL20:
6391 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6392 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6394 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6395 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6398 case RENDERPATH_GL11:
6399 case RENDERPATH_GL13:
6400 case RENDERPATH_GLES1:
6401 case RENDERPATH_GLES2:
6402 case RENDERPATH_D3D9:
6403 case RENDERPATH_D3D10:
6404 case RENDERPATH_D3D11:
6405 r_fb.usedepthtextures = false;
6407 case RENDERPATH_SOFT:
6408 r_fb.usedepthtextures = true;
6412 if (r_viewscale_fpsscaling.integer)
6414 double actualframetime;
6415 double targetframetime;
6417 actualframetime = r_refdef.lastdrawscreentime;
6418 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6419 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6420 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6421 if (r_viewscale_fpsscaling_stepsize.value > 0)
6422 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6423 viewscalefpsadjusted += adjust;
6424 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6427 viewscalefpsadjusted = 1.0f;
6429 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6431 switch(vid.renderpath)
6433 case RENDERPATH_GL20:
6434 case RENDERPATH_D3D9:
6435 case RENDERPATH_D3D10:
6436 case RENDERPATH_D3D11:
6437 case RENDERPATH_SOFT:
6438 case RENDERPATH_GLES2:
6440 case RENDERPATH_GL11:
6441 case RENDERPATH_GL13:
6442 case RENDERPATH_GLES1:
6446 // set bloomwidth and bloomheight to the bloom resolution that will be
6447 // used (often less than the screen resolution for faster rendering)
6448 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6449 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6450 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6451 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6452 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6454 // calculate desired texture sizes
6455 if (vid.support.arb_texture_non_power_of_two)
6457 screentexturewidth = vid.width;
6458 screentextureheight = vid.height;
6459 bloomtexturewidth = r_fb.bloomwidth;
6460 bloomtextureheight = r_fb.bloomheight;
6464 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6465 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6466 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6467 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6470 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))
6472 Cvar_SetValueQuick(&r_bloom, 0);
6473 Cvar_SetValueQuick(&r_motionblur, 0);
6474 Cvar_SetValueQuick(&r_damageblur, 0);
6477 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6479 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6481 && r_viewscale.value == 1.0f
6482 && !r_viewscale_fpsscaling.integer)
6483 screentexturewidth = screentextureheight = 0;
6484 if (!r_bloom.integer)
6485 bloomtexturewidth = bloomtextureheight = 0;
6487 // allocate textures as needed
6488 if (r_fb.screentexturewidth != screentexturewidth
6489 || r_fb.screentextureheight != screentextureheight
6490 || r_fb.bloomtexturewidth != bloomtexturewidth
6491 || r_fb.bloomtextureheight != bloomtextureheight
6492 || r_fb.textype != textype
6493 || useviewfbo != (r_fb.fbo != 0))
6495 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6497 if (r_fb.bloomtexture[i])
6498 R_FreeTexture(r_fb.bloomtexture[i]);
6499 r_fb.bloomtexture[i] = NULL;
6501 if (r_fb.bloomfbo[i])
6502 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6503 r_fb.bloomfbo[i] = 0;
6507 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6510 if (r_fb.colortexture)
6511 R_FreeTexture(r_fb.colortexture);
6512 r_fb.colortexture = NULL;
6514 if (r_fb.depthtexture)
6515 R_FreeTexture(r_fb.depthtexture);
6516 r_fb.depthtexture = NULL;
6518 if (r_fb.ghosttexture)
6519 R_FreeTexture(r_fb.ghosttexture);
6520 r_fb.ghosttexture = NULL;
6522 r_fb.screentexturewidth = screentexturewidth;
6523 r_fb.screentextureheight = screentextureheight;
6524 r_fb.bloomtexturewidth = bloomtexturewidth;
6525 r_fb.bloomtextureheight = bloomtextureheight;
6526 r_fb.textype = textype;
6528 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6530 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6531 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);
6532 r_fb.ghosttexture_valid = false;
6533 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);
6536 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6537 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6538 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6542 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6544 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6546 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);
6548 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6553 // bloom texture is a different resolution
6554 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6555 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6556 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6557 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6558 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6560 // set up a texcoord array for the full resolution screen image
6561 // (we have to keep this around to copy back during final render)
6562 r_fb.screentexcoord2f[0] = 0;
6563 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6564 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6565 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6566 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6567 r_fb.screentexcoord2f[5] = 0;
6568 r_fb.screentexcoord2f[6] = 0;
6569 r_fb.screentexcoord2f[7] = 0;
6573 for (i = 1;i < 8;i += 2)
6575 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6579 // set up a texcoord array for the reduced resolution bloom image
6580 // (which will be additive blended over the screen image)
6581 r_fb.bloomtexcoord2f[0] = 0;
6582 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6583 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6584 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6585 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6586 r_fb.bloomtexcoord2f[5] = 0;
6587 r_fb.bloomtexcoord2f[6] = 0;
6588 r_fb.bloomtexcoord2f[7] = 0;
6590 switch(vid.renderpath)
6592 case RENDERPATH_GL11:
6593 case RENDERPATH_GL13:
6594 case RENDERPATH_GL20:
6595 case RENDERPATH_SOFT:
6596 case RENDERPATH_GLES1:
6597 case RENDERPATH_GLES2:
6599 case RENDERPATH_D3D9:
6600 case RENDERPATH_D3D10:
6601 case RENDERPATH_D3D11:
6602 for (i = 0;i < 4;i++)
6604 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6605 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6606 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6607 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6612 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6615 r_refdef.view.clear = true;
6618 static void R_Bloom_MakeTexture(void)
6621 float xoffset, yoffset, r, brighten;
6623 float colorscale = r_bloom_colorscale.value;
6625 r_refdef.stats[r_stat_bloom]++;
6628 // this copy is unnecessary since it happens in R_BlendView already
6631 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);
6632 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6636 // scale down screen texture to the bloom texture size
6638 r_fb.bloomindex = 0;
6639 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6640 R_SetViewport(&r_fb.bloomviewport);
6641 GL_DepthTest(false);
6642 GL_BlendFunc(GL_ONE, GL_ZERO);
6643 GL_Color(colorscale, colorscale, colorscale, 1);
6644 // 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...
6645 switch(vid.renderpath)
6647 case RENDERPATH_GL11:
6648 case RENDERPATH_GL13:
6649 case RENDERPATH_GL20:
6650 case RENDERPATH_GLES1:
6651 case RENDERPATH_GLES2:
6652 case RENDERPATH_SOFT:
6653 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6655 case RENDERPATH_D3D9:
6656 case RENDERPATH_D3D10:
6657 case RENDERPATH_D3D11:
6658 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6661 // TODO: do boxfilter scale-down in shader?
6662 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6663 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6664 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6666 // we now have a properly scaled bloom image
6667 if (!r_fb.bloomfbo[r_fb.bloomindex])
6669 // copy it into the bloom texture
6670 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);
6671 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6674 // multiply bloom image by itself as many times as desired
6675 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6677 intex = r_fb.bloomtexture[r_fb.bloomindex];
6678 r_fb.bloomindex ^= 1;
6679 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6681 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6682 if (!r_fb.bloomfbo[r_fb.bloomindex])
6684 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6685 GL_Color(r,r,r,1); // apply fix factor
6690 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6691 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6692 GL_Color(1,1,1,1); // no fix factor supported here
6694 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6695 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6696 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6697 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6699 if (!r_fb.bloomfbo[r_fb.bloomindex])
6701 // copy the darkened image to a texture
6702 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);
6703 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6707 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6708 brighten = r_bloom_brighten.value;
6709 brighten = sqrt(brighten);
6711 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6713 for (dir = 0;dir < 2;dir++)
6715 intex = r_fb.bloomtexture[r_fb.bloomindex];
6716 r_fb.bloomindex ^= 1;
6717 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6718 // blend on at multiple vertical offsets to achieve a vertical blur
6719 // TODO: do offset blends using GLSL
6720 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6721 GL_BlendFunc(GL_ONE, GL_ZERO);
6722 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6723 for (x = -range;x <= range;x++)
6725 if (!dir){xoffset = 0;yoffset = x;}
6726 else {xoffset = x;yoffset = 0;}
6727 xoffset /= (float)r_fb.bloomtexturewidth;
6728 yoffset /= (float)r_fb.bloomtextureheight;
6729 // compute a texcoord array with the specified x and y offset
6730 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6731 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6732 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6733 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6734 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6735 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6736 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6737 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6738 // this r value looks like a 'dot' particle, fading sharply to
6739 // black at the edges
6740 // (probably not realistic but looks good enough)
6741 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6742 //r = brighten/(range*2+1);
6743 r = brighten / (range * 2 + 1);
6745 r *= (1 - x*x/(float)(range*range));
6746 GL_Color(r, r, r, 1);
6747 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6748 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6749 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6750 GL_BlendFunc(GL_ONE, GL_ONE);
6753 if (!r_fb.bloomfbo[r_fb.bloomindex])
6755 // copy the vertically or horizontally blurred bloom view to a texture
6756 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);
6757 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6762 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6764 unsigned int permutation;
6765 float uservecs[4][4];
6767 R_EntityMatrix(&identitymatrix);
6769 switch (vid.renderpath)
6771 case RENDERPATH_GL20:
6772 case RENDERPATH_D3D9:
6773 case RENDERPATH_D3D10:
6774 case RENDERPATH_D3D11:
6775 case RENDERPATH_SOFT:
6776 case RENDERPATH_GLES2:
6778 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6779 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6780 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6781 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6782 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6784 if (r_fb.colortexture)
6788 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);
6789 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6792 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6794 // declare variables
6795 float blur_factor, blur_mouseaccel, blur_velocity;
6796 static float blur_average;
6797 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6799 // set a goal for the factoring
6800 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6801 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6802 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6803 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6804 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6805 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6807 // from the goal, pick an averaged value between goal and last value
6808 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6809 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6811 // enforce minimum amount of blur
6812 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6814 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6816 // calculate values into a standard alpha
6817 cl.motionbluralpha = 1 - exp(-
6819 (r_motionblur.value * blur_factor / 80)
6821 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6824 max(0.0001, cl.time - cl.oldtime) // fps independent
6827 // randomization for the blur value to combat persistent ghosting
6828 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6829 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6832 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6833 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6835 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6836 GL_Color(1, 1, 1, cl.motionbluralpha);
6837 switch(vid.renderpath)
6839 case RENDERPATH_GL11:
6840 case RENDERPATH_GL13:
6841 case RENDERPATH_GL20:
6842 case RENDERPATH_GLES1:
6843 case RENDERPATH_GLES2:
6844 case RENDERPATH_SOFT:
6845 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6847 case RENDERPATH_D3D9:
6848 case RENDERPATH_D3D10:
6849 case RENDERPATH_D3D11:
6850 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6853 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6854 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6855 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6858 // updates old view angles for next pass
6859 VectorCopy(cl.viewangles, blur_oldangles);
6861 // copy view into the ghost texture
6862 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);
6863 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6864 r_fb.ghosttexture_valid = true;
6869 // no r_fb.colortexture means we're rendering to the real fb
6870 // we may still have to do view tint...
6871 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6873 // apply a color tint to the whole view
6874 R_ResetViewRendering2D(0, NULL, NULL);
6875 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6876 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6877 R_SetupShader_Generic_NoTexture(false, true);
6878 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6879 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6881 break; // no screen processing, no bloom, skip it
6884 if (r_fb.bloomtexture[0])
6886 // make the bloom texture
6887 R_Bloom_MakeTexture();
6890 #if _MSC_VER >= 1400
6891 #define sscanf sscanf_s
6893 memset(uservecs, 0, sizeof(uservecs));
6894 if (r_glsl_postprocess_uservec1_enable.integer)
6895 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6896 if (r_glsl_postprocess_uservec2_enable.integer)
6897 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6898 if (r_glsl_postprocess_uservec3_enable.integer)
6899 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6900 if (r_glsl_postprocess_uservec4_enable.integer)
6901 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6903 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6904 GL_Color(1, 1, 1, 1);
6905 GL_BlendFunc(GL_ONE, GL_ZERO);
6907 switch(vid.renderpath)
6909 case RENDERPATH_GL20:
6910 case RENDERPATH_GLES2:
6911 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6912 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6913 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6914 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6915 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6916 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]);
6917 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6918 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]);
6919 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]);
6920 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]);
6921 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]);
6922 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6923 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6924 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);
6926 case RENDERPATH_D3D9:
6928 // 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...
6929 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6930 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6931 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6932 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6933 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6934 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6935 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6936 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6937 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6938 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6939 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6940 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6941 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6942 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6945 case RENDERPATH_D3D10:
6946 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6948 case RENDERPATH_D3D11:
6949 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6951 case RENDERPATH_SOFT:
6952 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6953 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6954 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6955 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6956 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6957 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6958 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6959 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6960 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6961 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6962 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6963 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6964 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6965 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6970 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6971 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6973 case RENDERPATH_GL11:
6974 case RENDERPATH_GL13:
6975 case RENDERPATH_GLES1:
6976 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6978 // apply a color tint to the whole view
6979 R_ResetViewRendering2D(0, NULL, NULL);
6980 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6981 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6982 R_SetupShader_Generic_NoTexture(false, true);
6983 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6984 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6990 matrix4x4_t r_waterscrollmatrix;
6992 void R_UpdateFog(void)
6995 if (gamemode == GAME_NEHAHRA)
6997 if (gl_fogenable.integer)
6999 r_refdef.oldgl_fogenable = true;
7000 r_refdef.fog_density = gl_fogdensity.value;
7001 r_refdef.fog_red = gl_fogred.value;
7002 r_refdef.fog_green = gl_foggreen.value;
7003 r_refdef.fog_blue = gl_fogblue.value;
7004 r_refdef.fog_alpha = 1;
7005 r_refdef.fog_start = 0;
7006 r_refdef.fog_end = gl_skyclip.value;
7007 r_refdef.fog_height = 1<<30;
7008 r_refdef.fog_fadedepth = 128;
7010 else if (r_refdef.oldgl_fogenable)
7012 r_refdef.oldgl_fogenable = false;
7013 r_refdef.fog_density = 0;
7014 r_refdef.fog_red = 0;
7015 r_refdef.fog_green = 0;
7016 r_refdef.fog_blue = 0;
7017 r_refdef.fog_alpha = 0;
7018 r_refdef.fog_start = 0;
7019 r_refdef.fog_end = 0;
7020 r_refdef.fog_height = 1<<30;
7021 r_refdef.fog_fadedepth = 128;
7026 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7027 r_refdef.fog_start = max(0, r_refdef.fog_start);
7028 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7030 if (r_refdef.fog_density && r_drawfog.integer)
7032 r_refdef.fogenabled = true;
7033 // this is the point where the fog reaches 0.9986 alpha, which we
7034 // consider a good enough cutoff point for the texture
7035 // (0.9986 * 256 == 255.6)
7036 if (r_fog_exp2.integer)
7037 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7039 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7040 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7041 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7042 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7043 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7044 R_BuildFogHeightTexture();
7045 // fog color was already set
7046 // update the fog texture
7047 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)
7048 R_BuildFogTexture();
7049 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7050 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7053 r_refdef.fogenabled = false;
7056 if (r_refdef.fog_density)
7058 r_refdef.fogcolor[0] = r_refdef.fog_red;
7059 r_refdef.fogcolor[1] = r_refdef.fog_green;
7060 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7062 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7063 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7064 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7065 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7069 VectorCopy(r_refdef.fogcolor, fogvec);
7070 // color.rgb *= ContrastBoost * SceneBrightness;
7071 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7072 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7073 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7074 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7079 void R_UpdateVariables(void)
7083 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7085 r_refdef.farclip = r_farclip_base.value;
7086 if (r_refdef.scene.worldmodel)
7087 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7088 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7090 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7091 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7092 r_refdef.polygonfactor = 0;
7093 r_refdef.polygonoffset = 0;
7094 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7095 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7097 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7098 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7099 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7100 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7101 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7102 if (FAKELIGHT_ENABLED)
7104 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7106 else if (r_refdef.scene.worldmodel)
7108 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7110 if (r_showsurfaces.integer)
7112 r_refdef.scene.rtworld = false;
7113 r_refdef.scene.rtworldshadows = false;
7114 r_refdef.scene.rtdlight = false;
7115 r_refdef.scene.rtdlightshadows = false;
7116 r_refdef.lightmapintensity = 0;
7119 r_gpuskeletal = false;
7120 switch(vid.renderpath)
7122 case RENDERPATH_GL20:
7123 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7124 case RENDERPATH_D3D9:
7125 case RENDERPATH_D3D10:
7126 case RENDERPATH_D3D11:
7127 case RENDERPATH_SOFT:
7128 case RENDERPATH_GLES2:
7129 if(v_glslgamma.integer && !vid_gammatables_trivial)
7131 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7133 // build GLSL gamma texture
7134 #define RAMPWIDTH 256
7135 unsigned short ramp[RAMPWIDTH * 3];
7136 unsigned char rampbgr[RAMPWIDTH][4];
7139 r_texture_gammaramps_serial = vid_gammatables_serial;
7141 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7142 for(i = 0; i < RAMPWIDTH; ++i)
7144 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7145 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7146 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7149 if (r_texture_gammaramps)
7151 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7155 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7161 // remove GLSL gamma texture
7164 case RENDERPATH_GL11:
7165 case RENDERPATH_GL13:
7166 case RENDERPATH_GLES1:
7171 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7172 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7178 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7179 if( scenetype != r_currentscenetype ) {
7180 // store the old scenetype
7181 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7182 r_currentscenetype = scenetype;
7183 // move in the new scene
7184 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7193 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7195 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7196 if( scenetype == r_currentscenetype ) {
7197 return &r_refdef.scene;
7199 return &r_scenes_store[ scenetype ];
7203 static int R_SortEntities_Compare(const void *ap, const void *bp)
7205 const entity_render_t *a = *(const entity_render_t **)ap;
7206 const entity_render_t *b = *(const entity_render_t **)bp;
7209 if(a->model < b->model)
7211 if(a->model > b->model)
7215 // TODO possibly calculate the REAL skinnum here first using
7217 if(a->skinnum < b->skinnum)
7219 if(a->skinnum > b->skinnum)
7222 // everything we compared is equal
7225 static void R_SortEntities(void)
7227 // below or equal 2 ents, sorting never gains anything
7228 if(r_refdef.scene.numentities <= 2)
7231 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7239 int dpsoftrast_test;
7240 extern cvar_t r_shadow_bouncegrid;
7241 void R_RenderView(void)
7243 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7245 rtexture_t *depthtexture;
7246 rtexture_t *colortexture;
7248 dpsoftrast_test = r_test.integer;
7250 if (r_timereport_active)
7251 R_TimeReport("start");
7252 r_textureframe++; // used only by R_GetCurrentTexture
7253 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7255 if(R_CompileShader_CheckStaticParms())
7258 if (!r_drawentities.integer)
7259 r_refdef.scene.numentities = 0;
7260 else if (r_sortentities.integer)
7263 R_AnimCache_ClearCache();
7265 /* adjust for stereo display */
7266 if(R_Stereo_Active())
7268 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);
7269 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7272 if (r_refdef.view.isoverlay)
7274 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7275 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7276 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7277 R_TimeReport("depthclear");
7279 r_refdef.view.showdebug = false;
7281 r_fb.water.enabled = false;
7282 r_fb.water.numwaterplanes = 0;
7284 R_RenderScene(0, NULL, NULL);
7286 r_refdef.view.matrix = originalmatrix;
7292 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7294 r_refdef.view.matrix = originalmatrix;
7298 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7300 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7301 // in sRGB fallback, behave similar to true sRGB: convert this
7302 // value from linear to sRGB
7303 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7305 R_RenderView_UpdateViewVectors();
7307 R_Shadow_UpdateWorldLightSelection();
7309 R_Bloom_StartFrame();
7311 // apply bloom brightness offset
7312 if(r_fb.bloomtexture[0])
7313 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7315 R_Water_StartFrame();
7317 // now we probably have an fbo to render into
7319 depthtexture = r_fb.depthtexture;
7320 colortexture = r_fb.colortexture;
7323 if (r_timereport_active)
7324 R_TimeReport("viewsetup");
7326 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7328 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7330 R_ClearScreen(r_refdef.fogenabled);
7331 if (r_timereport_active)
7332 R_TimeReport("viewclear");
7334 r_refdef.view.clear = true;
7336 r_refdef.view.showdebug = true;
7339 if (r_timereport_active)
7340 R_TimeReport("visibility");
7342 R_AnimCache_CacheVisibleEntities();
7343 if (r_timereport_active)
7344 R_TimeReport("animcache");
7346 R_Shadow_UpdateBounceGridTexture();
7347 if (r_timereport_active && r_shadow_bouncegrid.integer)
7348 R_TimeReport("bouncegrid");
7350 r_fb.water.numwaterplanes = 0;
7351 if (r_fb.water.enabled)
7352 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7354 R_RenderScene(fbo, depthtexture, colortexture);
7355 r_fb.water.numwaterplanes = 0;
7357 R_BlendView(fbo, depthtexture, colortexture);
7358 if (r_timereport_active)
7359 R_TimeReport("blendview");
7361 GL_Scissor(0, 0, vid.width, vid.height);
7362 GL_ScissorTest(false);
7364 r_refdef.view.matrix = originalmatrix;
7369 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7371 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7373 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7374 if (r_timereport_active)
7375 R_TimeReport("waterworld");
7378 // don't let sound skip if going slow
7379 if (r_refdef.scene.extraupdate)
7382 R_DrawModelsAddWaterPlanes();
7383 if (r_timereport_active)
7384 R_TimeReport("watermodels");
7386 if (r_fb.water.numwaterplanes)
7388 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7389 if (r_timereport_active)
7390 R_TimeReport("waterscenes");
7394 extern cvar_t cl_locs_show;
7395 static void R_DrawLocs(void);
7396 static void R_DrawEntityBBoxes(void);
7397 static void R_DrawModelDecals(void);
7398 extern cvar_t cl_decals_newsystem;
7399 extern qboolean r_shadow_usingdeferredprepass;
7400 extern int r_shadow_shadowmapatlas_modelshadows_size;
7401 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7403 qboolean shadowmapping = false;
7405 if (r_timereport_active)
7406 R_TimeReport("beginscene");
7408 r_refdef.stats[r_stat_renders]++;
7412 // don't let sound skip if going slow
7413 if (r_refdef.scene.extraupdate)
7416 R_MeshQueue_BeginScene();
7420 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);
7422 if (r_timereport_active)
7423 R_TimeReport("skystartframe");
7425 if (cl.csqc_vidvars.drawworld)
7427 // don't let sound skip if going slow
7428 if (r_refdef.scene.extraupdate)
7431 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7433 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7434 if (r_timereport_active)
7435 R_TimeReport("worldsky");
7438 if (R_DrawBrushModelsSky() && r_timereport_active)
7439 R_TimeReport("bmodelsky");
7441 if (skyrendermasked && skyrenderlater)
7443 // we have to force off the water clipping plane while rendering sky
7444 R_SetupView(false, fbo, depthtexture, colortexture);
7446 R_SetupView(true, fbo, depthtexture, colortexture);
7447 if (r_timereport_active)
7448 R_TimeReport("sky");
7452 R_Shadow_PrepareModelShadows();
7453 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7454 if (r_timereport_active)
7455 R_TimeReport("preparelights");
7457 // render all the shadowmaps that will be used for this view
7458 shadowmapping = R_Shadow_ShadowMappingEnabled();
7459 if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7461 R_Shadow_DrawShadowMaps();
7462 if (r_timereport_active)
7463 R_TimeReport("shadowmaps");
7466 // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7467 if (r_shadow_usingdeferredprepass)
7468 R_Shadow_DrawPrepass();
7470 // now we begin the forward pass of the view render
7471 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7473 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7474 if (r_timereport_active)
7475 R_TimeReport("worlddepth");
7477 if (r_depthfirst.integer >= 2)
7479 R_DrawModelsDepth();
7480 if (r_timereport_active)
7481 R_TimeReport("modeldepth");
7484 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7486 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7487 if (r_timereport_active)
7488 R_TimeReport("world");
7491 // don't let sound skip if going slow
7492 if (r_refdef.scene.extraupdate)
7496 if (r_timereport_active)
7497 R_TimeReport("models");
7499 // don't let sound skip if going slow
7500 if (r_refdef.scene.extraupdate)
7503 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7505 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7506 R_Shadow_DrawModelShadows();
7507 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7508 // don't let sound skip if going slow
7509 if (r_refdef.scene.extraupdate)
7513 if (!r_shadow_usingdeferredprepass)
7515 R_Shadow_DrawLights();
7516 if (r_timereport_active)
7517 R_TimeReport("rtlights");
7520 // don't let sound skip if going slow
7521 if (r_refdef.scene.extraupdate)
7524 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7526 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7527 R_Shadow_DrawModelShadows();
7528 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7529 // don't let sound skip if going slow
7530 if (r_refdef.scene.extraupdate)
7534 if (cl.csqc_vidvars.drawworld)
7536 if (cl_decals_newsystem.integer)
7538 R_DrawModelDecals();
7539 if (r_timereport_active)
7540 R_TimeReport("modeldecals");
7545 if (r_timereport_active)
7546 R_TimeReport("decals");
7550 if (r_timereport_active)
7551 R_TimeReport("particles");
7554 if (r_timereport_active)
7555 R_TimeReport("explosions");
7557 R_DrawLightningBeams();
7558 if (r_timereport_active)
7559 R_TimeReport("lightning");
7563 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7565 if (r_refdef.view.showdebug)
7567 if (cl_locs_show.integer)
7570 if (r_timereport_active)
7571 R_TimeReport("showlocs");
7574 if (r_drawportals.integer)
7577 if (r_timereport_active)
7578 R_TimeReport("portals");
7581 if (r_showbboxes.value > 0)
7583 R_DrawEntityBBoxes();
7584 if (r_timereport_active)
7585 R_TimeReport("bboxes");
7589 if (r_transparent.integer)
7591 R_MeshQueue_RenderTransparent();
7592 if (r_timereport_active)
7593 R_TimeReport("drawtrans");
7596 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))
7598 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7599 if (r_timereport_active)
7600 R_TimeReport("worlddebug");
7601 R_DrawModelsDebug();
7602 if (r_timereport_active)
7603 R_TimeReport("modeldebug");
7606 if (cl.csqc_vidvars.drawworld)
7608 R_Shadow_DrawCoronas();
7609 if (r_timereport_active)
7610 R_TimeReport("coronas");
7615 GL_DepthTest(false);
7616 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7617 GL_Color(1, 1, 1, 1);
7618 qglBegin(GL_POLYGON);
7619 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7620 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7621 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7622 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7624 qglBegin(GL_POLYGON);
7625 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]);
7626 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]);
7627 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]);
7628 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]);
7630 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7634 // don't let sound skip if going slow
7635 if (r_refdef.scene.extraupdate)
7639 static const unsigned short bboxelements[36] =
7649 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7652 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7654 RSurf_ActiveWorldEntity();
7656 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7657 GL_DepthMask(false);
7658 GL_DepthRange(0, 1);
7659 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7660 // R_Mesh_ResetTextureState();
7662 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7663 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7664 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7665 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7666 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7667 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7668 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7669 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7670 R_FillColors(color4f, 8, cr, cg, cb, ca);
7671 if (r_refdef.fogenabled)
7673 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7675 f1 = RSurf_FogVertex(v);
7677 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7678 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7679 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7682 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7683 R_Mesh_ResetTextureState();
7684 R_SetupShader_Generic_NoTexture(false, false);
7685 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7688 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7690 prvm_prog_t *prog = SVVM_prog;
7693 prvm_edict_t *edict;
7695 // this function draws bounding boxes of server entities
7699 GL_CullFace(GL_NONE);
7700 R_SetupShader_Generic_NoTexture(false, false);
7702 for (i = 0;i < numsurfaces;i++)
7704 edict = PRVM_EDICT_NUM(surfacelist[i]);
7705 switch ((int)PRVM_serveredictfloat(edict, solid))
7707 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7708 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7709 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7710 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7711 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7712 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7713 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7715 color[3] *= r_showbboxes.value;
7716 color[3] = bound(0, color[3], 1);
7717 GL_DepthTest(!r_showdisabledepthtest.integer);
7718 GL_CullFace(r_refdef.view.cullface_front);
7719 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7723 static void R_DrawEntityBBoxes(void)
7726 prvm_edict_t *edict;
7728 prvm_prog_t *prog = SVVM_prog;
7730 // this function draws bounding boxes of server entities
7734 for (i = 0;i < prog->num_edicts;i++)
7736 edict = PRVM_EDICT_NUM(i);
7737 if (edict->priv.server->free)
7739 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7740 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7742 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7744 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7745 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7749 static const int nomodelelement3i[24] =
7761 static const unsigned short nomodelelement3s[24] =
7773 static const float nomodelvertex3f[6*3] =
7783 static const float nomodelcolor4f[6*4] =
7785 0.0f, 0.0f, 0.5f, 1.0f,
7786 0.0f, 0.0f, 0.5f, 1.0f,
7787 0.0f, 0.5f, 0.0f, 1.0f,
7788 0.0f, 0.5f, 0.0f, 1.0f,
7789 0.5f, 0.0f, 0.0f, 1.0f,
7790 0.5f, 0.0f, 0.0f, 1.0f
7793 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7799 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);
7801 // this is only called once per entity so numsurfaces is always 1, and
7802 // surfacelist is always {0}, so this code does not handle batches
7804 if (rsurface.ent_flags & RENDER_ADDITIVE)
7806 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7807 GL_DepthMask(false);
7809 else if (rsurface.colormod[3] < 1)
7811 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7812 GL_DepthMask(false);
7816 GL_BlendFunc(GL_ONE, GL_ZERO);
7819 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7820 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7821 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7822 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7823 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7824 for (i = 0, c = color4f;i < 6;i++, c += 4)
7826 c[0] *= rsurface.colormod[0];
7827 c[1] *= rsurface.colormod[1];
7828 c[2] *= rsurface.colormod[2];
7829 c[3] *= rsurface.colormod[3];
7831 if (r_refdef.fogenabled)
7833 for (i = 0, c = color4f;i < 6;i++, c += 4)
7835 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7837 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7838 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7839 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7842 // R_Mesh_ResetTextureState();
7843 R_SetupShader_Generic_NoTexture(false, false);
7844 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7845 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7848 void R_DrawNoModel(entity_render_t *ent)
7851 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7852 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7853 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7855 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7858 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7860 vec3_t right1, right2, diff, normal;
7862 VectorSubtract (org2, org1, normal);
7864 // calculate 'right' vector for start
7865 VectorSubtract (r_refdef.view.origin, org1, diff);
7866 CrossProduct (normal, diff, right1);
7867 VectorNormalize (right1);
7869 // calculate 'right' vector for end
7870 VectorSubtract (r_refdef.view.origin, org2, diff);
7871 CrossProduct (normal, diff, right2);
7872 VectorNormalize (right2);
7874 vert[ 0] = org1[0] + width * right1[0];
7875 vert[ 1] = org1[1] + width * right1[1];
7876 vert[ 2] = org1[2] + width * right1[2];
7877 vert[ 3] = org1[0] - width * right1[0];
7878 vert[ 4] = org1[1] - width * right1[1];
7879 vert[ 5] = org1[2] - width * right1[2];
7880 vert[ 6] = org2[0] - width * right2[0];
7881 vert[ 7] = org2[1] - width * right2[1];
7882 vert[ 8] = org2[2] - width * right2[2];
7883 vert[ 9] = org2[0] + width * right2[0];
7884 vert[10] = org2[1] + width * right2[1];
7885 vert[11] = org2[2] + width * right2[2];
7888 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)
7890 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7891 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7892 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7893 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7894 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7895 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7896 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7897 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7898 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7899 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7900 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7901 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7904 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7909 VectorSet(v, x, y, z);
7910 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7911 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7913 if (i == mesh->numvertices)
7915 if (mesh->numvertices < mesh->maxvertices)
7917 VectorCopy(v, vertex3f);
7918 mesh->numvertices++;
7920 return mesh->numvertices;
7926 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7930 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7931 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7932 e = mesh->element3i + mesh->numtriangles * 3;
7933 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7935 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7936 if (mesh->numtriangles < mesh->maxtriangles)
7941 mesh->numtriangles++;
7943 element[1] = element[2];
7947 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7951 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7952 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7953 e = mesh->element3i + mesh->numtriangles * 3;
7954 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7956 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7957 if (mesh->numtriangles < mesh->maxtriangles)
7962 mesh->numtriangles++;
7964 element[1] = element[2];
7968 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7969 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7971 int planenum, planenum2;
7974 mplane_t *plane, *plane2;
7976 double temppoints[2][256*3];
7977 // figure out how large a bounding box we need to properly compute this brush
7979 for (w = 0;w < numplanes;w++)
7980 maxdist = max(maxdist, fabs(planes[w].dist));
7981 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7982 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7983 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7987 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7988 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7990 if (planenum2 == planenum)
7992 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);
7995 if (tempnumpoints < 3)
7997 // generate elements forming a triangle fan for this polygon
7998 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8002 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)
8004 texturelayer_t *layer;
8005 layer = t->currentlayers + t->currentnumlayers++;
8007 layer->depthmask = depthmask;
8008 layer->blendfunc1 = blendfunc1;
8009 layer->blendfunc2 = blendfunc2;
8010 layer->texture = texture;
8011 layer->texmatrix = *matrix;
8012 layer->color[0] = r;
8013 layer->color[1] = g;
8014 layer->color[2] = b;
8015 layer->color[3] = a;
8018 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8020 if(parms[0] == 0 && parms[1] == 0)
8022 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8023 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8028 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8031 index = parms[2] + rsurface.shadertime * parms[3];
8032 index -= floor(index);
8033 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8036 case Q3WAVEFUNC_NONE:
8037 case Q3WAVEFUNC_NOISE:
8038 case Q3WAVEFUNC_COUNT:
8041 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8042 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8043 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8044 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8045 case Q3WAVEFUNC_TRIANGLE:
8047 f = index - floor(index);
8060 f = parms[0] + parms[1] * f;
8061 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8062 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8066 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8073 matrix4x4_t matrix, temp;
8074 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8075 // it's better to have one huge fixup every 9 hours than gradual
8076 // degradation over time which looks consistently bad after many hours.
8078 // tcmod scroll in particular suffers from this degradation which can't be
8079 // effectively worked around even with floor() tricks because we don't
8080 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8081 // a workaround involving floor() would be incorrect anyway...
8082 shadertime = rsurface.shadertime;
8083 if (shadertime >= 32768.0f)
8084 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8085 switch(tcmod->tcmod)
8089 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8090 matrix = r_waterscrollmatrix;
8092 matrix = identitymatrix;
8094 case Q3TCMOD_ENTITYTRANSLATE:
8095 // this is used in Q3 to allow the gamecode to control texcoord
8096 // scrolling on the entity, which is not supported in darkplaces yet.
8097 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8099 case Q3TCMOD_ROTATE:
8100 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8101 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8102 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8105 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8107 case Q3TCMOD_SCROLL:
8108 // this particular tcmod is a "bug for bug" compatible one with regards to
8109 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8110 // specifically did the wrapping and so we must mimic that...
8111 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8112 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8113 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8115 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8116 w = (int) tcmod->parms[0];
8117 h = (int) tcmod->parms[1];
8118 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8120 idx = (int) floor(f * w * h);
8121 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8123 case Q3TCMOD_STRETCH:
8124 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8125 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8127 case Q3TCMOD_TRANSFORM:
8128 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8129 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8130 VectorSet(tcmat + 6, 0 , 0 , 1);
8131 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8132 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8134 case Q3TCMOD_TURBULENT:
8135 // this is handled in the RSurf_PrepareVertices function
8136 matrix = identitymatrix;
8140 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8143 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8145 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8146 char name[MAX_QPATH];
8147 skinframe_t *skinframe;
8148 unsigned char pixels[296*194];
8149 strlcpy(cache->name, skinname, sizeof(cache->name));
8150 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8151 if (developer_loading.integer)
8152 Con_Printf("loading %s\n", name);
8153 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8154 if (!skinframe || !skinframe->base)
8157 fs_offset_t filesize;
8159 f = FS_LoadFile(name, tempmempool, true, &filesize);
8162 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8163 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8167 cache->skinframe = skinframe;
8170 texture_t *R_GetCurrentTexture(texture_t *t)
8173 const entity_render_t *ent = rsurface.entity;
8174 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8175 q3shaderinfo_layer_tcmod_t *tcmod;
8177 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8178 return t->currentframe;
8179 t->update_lastrenderframe = r_textureframe;
8180 t->update_lastrenderentity = (void *)ent;
8182 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8183 t->camera_entity = ent->entitynumber;
8185 t->camera_entity = 0;
8187 // switch to an alternate material if this is a q1bsp animated material
8189 texture_t *texture = t;
8190 int s = rsurface.ent_skinnum;
8191 if ((unsigned int)s >= (unsigned int)model->numskins)
8193 if (model->skinscenes)
8195 if (model->skinscenes[s].framecount > 1)
8196 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8198 s = model->skinscenes[s].firstframe;
8201 t = t + s * model->num_surfaces;
8204 // use an alternate animation if the entity's frame is not 0,
8205 // and only if the texture has an alternate animation
8206 if (t->animated == 2) // q2bsp
8207 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8208 else if (rsurface.ent_alttextures && t->anim_total[1])
8209 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8211 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8213 texture->currentframe = t;
8216 // update currentskinframe to be a qw skin or animation frame
8217 if (rsurface.ent_qwskin >= 0)
8219 i = rsurface.ent_qwskin;
8220 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8222 r_qwskincache_size = cl.maxclients;
8224 Mem_Free(r_qwskincache);
8225 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8227 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8228 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8229 t->currentskinframe = r_qwskincache[i].skinframe;
8230 if (t->currentskinframe == NULL)
8231 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8233 else if (t->numskinframes >= 2)
8234 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8235 if (t->backgroundnumskinframes >= 2)
8236 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8238 t->currentmaterialflags = t->basematerialflags;
8239 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8240 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8241 t->currentalpha *= r_wateralpha.value;
8242 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8243 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8244 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8245 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8246 if (!(rsurface.ent_flags & RENDER_LIGHT))
8247 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8248 else if (FAKELIGHT_ENABLED)
8250 // no modellight if using fakelight for the map
8252 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8254 // pick a model lighting mode
8255 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8256 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8258 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8260 if (rsurface.ent_flags & RENDER_ADDITIVE)
8261 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8262 else if (t->currentalpha < 1)
8263 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8264 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8265 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8266 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8267 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8268 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8269 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8270 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8271 if (t->backgroundnumskinframes)
8272 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8273 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8275 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8276 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8279 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8280 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8282 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8283 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8285 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8286 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8288 // there is no tcmod
8289 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8291 t->currenttexmatrix = r_waterscrollmatrix;
8292 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8294 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8296 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8297 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8300 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8301 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8302 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8303 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8305 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8306 if (t->currentskinframe->qpixels)
8307 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8308 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8309 if (!t->basetexture)
8310 t->basetexture = r_texture_notexture;
8311 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8312 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8313 t->nmaptexture = t->currentskinframe->nmap;
8314 if (!t->nmaptexture)
8315 t->nmaptexture = r_texture_blanknormalmap;
8316 t->glosstexture = r_texture_black;
8317 t->glowtexture = t->currentskinframe->glow;
8318 t->fogtexture = t->currentskinframe->fog;
8319 t->reflectmasktexture = t->currentskinframe->reflect;
8320 if (t->backgroundnumskinframes)
8322 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8323 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8324 t->backgroundglosstexture = r_texture_black;
8325 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8326 if (!t->backgroundnmaptexture)
8327 t->backgroundnmaptexture = r_texture_blanknormalmap;
8328 // make sure that if glow is going to be used, both textures are not NULL
8329 if (!t->backgroundglowtexture && t->glowtexture)
8330 t->backgroundglowtexture = r_texture_black;
8331 if (!t->glowtexture && t->backgroundglowtexture)
8332 t->glowtexture = r_texture_black;
8336 t->backgroundbasetexture = r_texture_white;
8337 t->backgroundnmaptexture = r_texture_blanknormalmap;
8338 t->backgroundglosstexture = r_texture_black;
8339 t->backgroundglowtexture = NULL;
8341 t->specularpower = r_shadow_glossexponent.value;
8342 // TODO: store reference values for these in the texture?
8343 t->specularscale = 0;
8344 if (r_shadow_gloss.integer > 0)
8346 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8348 if (r_shadow_glossintensity.value > 0)
8350 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8351 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8352 t->specularscale = r_shadow_glossintensity.value;
8355 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8357 t->glosstexture = r_texture_white;
8358 t->backgroundglosstexture = r_texture_white;
8359 t->specularscale = r_shadow_gloss2intensity.value;
8360 t->specularpower = r_shadow_gloss2exponent.value;
8363 t->specularscale *= t->specularscalemod;
8364 t->specularpower *= t->specularpowermod;
8365 t->rtlightambient = 0;
8367 // lightmaps mode looks bad with dlights using actual texturing, so turn
8368 // off the colormap and glossmap, but leave the normalmap on as it still
8369 // accurately represents the shading involved
8370 if (gl_lightmaps.integer)
8372 t->basetexture = r_texture_grey128;
8373 t->pantstexture = r_texture_black;
8374 t->shirttexture = r_texture_black;
8375 if (gl_lightmaps.integer < 2)
8376 t->nmaptexture = r_texture_blanknormalmap;
8377 t->glosstexture = r_texture_black;
8378 t->glowtexture = NULL;
8379 t->fogtexture = NULL;
8380 t->reflectmasktexture = NULL;
8381 t->backgroundbasetexture = NULL;
8382 if (gl_lightmaps.integer < 2)
8383 t->backgroundnmaptexture = r_texture_blanknormalmap;
8384 t->backgroundglosstexture = r_texture_black;
8385 t->backgroundglowtexture = NULL;
8386 t->specularscale = 0;
8387 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8390 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8391 VectorClear(t->dlightcolor);
8392 t->currentnumlayers = 0;
8393 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8395 int blendfunc1, blendfunc2;
8397 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8399 blendfunc1 = GL_SRC_ALPHA;
8400 blendfunc2 = GL_ONE;
8402 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8404 blendfunc1 = GL_SRC_ALPHA;
8405 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8407 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8409 blendfunc1 = t->customblendfunc[0];
8410 blendfunc2 = t->customblendfunc[1];
8414 blendfunc1 = GL_ONE;
8415 blendfunc2 = GL_ZERO;
8417 // don't colormod evilblend textures
8418 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8419 VectorSet(t->lightmapcolor, 1, 1, 1);
8420 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8421 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8423 // fullbright is not affected by r_refdef.lightmapintensity
8424 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]);
8425 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8426 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]);
8427 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8428 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]);
8432 vec3_t ambientcolor;
8434 // set the color tint used for lights affecting this surface
8435 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8437 // q3bsp has no lightmap updates, so the lightstylevalue that
8438 // would normally be baked into the lightmap must be
8439 // applied to the color
8440 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8441 if (model->type == mod_brushq3)
8442 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8443 colorscale *= r_refdef.lightmapintensity;
8444 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8445 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8446 // basic lit geometry
8447 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]);
8448 // add pants/shirt if needed
8449 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8450 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]);
8451 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8452 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]);
8453 // now add ambient passes if needed
8454 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8456 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]);
8457 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8458 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]);
8459 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8460 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]);
8463 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8464 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]);
8465 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8467 // if this is opaque use alpha blend which will darken the earlier
8470 // if this is an alpha blended material, all the earlier passes
8471 // were darkened by fog already, so we only need to add the fog
8472 // color ontop through the fog mask texture
8474 // if this is an additive blended material, all the earlier passes
8475 // were darkened by fog already, and we should not add fog color
8476 // (because the background was not darkened, there is no fog color
8477 // that was lost behind it).
8478 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]);
8485 rsurfacestate_t rsurface;
8487 void RSurf_ActiveWorldEntity(void)
8489 dp_model_t *model = r_refdef.scene.worldmodel;
8490 //if (rsurface.entity == r_refdef.scene.worldentity)
8492 rsurface.entity = r_refdef.scene.worldentity;
8493 rsurface.skeleton = NULL;
8494 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8495 rsurface.ent_skinnum = 0;
8496 rsurface.ent_qwskin = -1;
8497 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8498 rsurface.shadertime = r_refdef.scene.time;
8499 rsurface.matrix = identitymatrix;
8500 rsurface.inversematrix = identitymatrix;
8501 rsurface.matrixscale = 1;
8502 rsurface.inversematrixscale = 1;
8503 R_EntityMatrix(&identitymatrix);
8504 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8505 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8506 rsurface.fograngerecip = r_refdef.fograngerecip;
8507 rsurface.fogheightfade = r_refdef.fogheightfade;
8508 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8509 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8510 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8511 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8512 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8513 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8514 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8515 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8516 rsurface.colormod[3] = 1;
8517 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);
8518 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8519 rsurface.frameblend[0].lerp = 1;
8520 rsurface.ent_alttextures = false;
8521 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8522 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8523 rsurface.entityskeletaltransform3x4 = NULL;
8524 rsurface.entityskeletaltransform3x4buffer = NULL;
8525 rsurface.entityskeletaltransform3x4offset = 0;
8526 rsurface.entityskeletaltransform3x4size = 0;;
8527 rsurface.entityskeletalnumtransforms = 0;
8528 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8529 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8530 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8531 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8532 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8533 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8534 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8535 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8536 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8537 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8538 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8539 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8540 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8541 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8542 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8543 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8544 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8545 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8546 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8547 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8548 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8549 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8550 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8551 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8552 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8553 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8554 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8555 rsurface.modelelement3i = model->surfmesh.data_element3i;
8556 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8557 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8558 rsurface.modelelement3s = model->surfmesh.data_element3s;
8559 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8560 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8561 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8562 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8563 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8564 rsurface.modelsurfaces = model->data_surfaces;
8565 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8566 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8567 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8568 rsurface.modelgeneratedvertex = false;
8569 rsurface.batchgeneratedvertex = false;
8570 rsurface.batchfirstvertex = 0;
8571 rsurface.batchnumvertices = 0;
8572 rsurface.batchfirsttriangle = 0;
8573 rsurface.batchnumtriangles = 0;
8574 rsurface.batchvertex3f = NULL;
8575 rsurface.batchvertex3f_vertexbuffer = NULL;
8576 rsurface.batchvertex3f_bufferoffset = 0;
8577 rsurface.batchsvector3f = NULL;
8578 rsurface.batchsvector3f_vertexbuffer = NULL;
8579 rsurface.batchsvector3f_bufferoffset = 0;
8580 rsurface.batchtvector3f = NULL;
8581 rsurface.batchtvector3f_vertexbuffer = NULL;
8582 rsurface.batchtvector3f_bufferoffset = 0;
8583 rsurface.batchnormal3f = NULL;
8584 rsurface.batchnormal3f_vertexbuffer = NULL;
8585 rsurface.batchnormal3f_bufferoffset = 0;
8586 rsurface.batchlightmapcolor4f = NULL;
8587 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8588 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8589 rsurface.batchtexcoordtexture2f = NULL;
8590 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8591 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8592 rsurface.batchtexcoordlightmap2f = NULL;
8593 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8594 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8595 rsurface.batchskeletalindex4ub = NULL;
8596 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8597 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8598 rsurface.batchskeletalweight4ub = NULL;
8599 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8600 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8601 rsurface.batchvertexmesh = NULL;
8602 rsurface.batchvertexmesh_vertexbuffer = NULL;
8603 rsurface.batchvertexmesh_bufferoffset = 0;
8604 rsurface.batchelement3i = NULL;
8605 rsurface.batchelement3i_indexbuffer = NULL;
8606 rsurface.batchelement3i_bufferoffset = 0;
8607 rsurface.batchelement3s = NULL;
8608 rsurface.batchelement3s_indexbuffer = NULL;
8609 rsurface.batchelement3s_bufferoffset = 0;
8610 rsurface.passcolor4f = NULL;
8611 rsurface.passcolor4f_vertexbuffer = NULL;
8612 rsurface.passcolor4f_bufferoffset = 0;
8613 rsurface.forcecurrenttextureupdate = false;
8616 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8618 dp_model_t *model = ent->model;
8619 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8621 rsurface.entity = (entity_render_t *)ent;
8622 rsurface.skeleton = ent->skeleton;
8623 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8624 rsurface.ent_skinnum = ent->skinnum;
8625 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;
8626 rsurface.ent_flags = ent->flags;
8627 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8628 rsurface.matrix = ent->matrix;
8629 rsurface.inversematrix = ent->inversematrix;
8630 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8631 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8632 R_EntityMatrix(&rsurface.matrix);
8633 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8634 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8635 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8636 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8637 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8638 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8639 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8640 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8641 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8642 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8643 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8644 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8645 rsurface.colormod[3] = ent->alpha;
8646 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8647 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8648 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8649 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8650 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8651 if (ent->model->brush.submodel && !prepass)
8653 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8654 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8656 // if the animcache code decided it should use the shader path, skip the deform step
8657 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8658 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8659 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8660 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8661 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8662 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8664 if (ent->animcache_vertex3f)
8666 r_refdef.stats[r_stat_batch_entitycache_count]++;
8667 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8668 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8669 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8670 rsurface.modelvertex3f = ent->animcache_vertex3f;
8671 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8672 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8673 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8674 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8675 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8676 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8677 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8678 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8679 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8680 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8681 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8682 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8683 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8684 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8686 else if (wanttangents)
8688 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8689 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8690 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8691 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8692 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8693 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8694 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8695 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8696 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8697 rsurface.modelvertexmesh = NULL;
8698 rsurface.modelvertexmesh_vertexbuffer = NULL;
8699 rsurface.modelvertexmesh_bufferoffset = 0;
8700 rsurface.modelvertex3f_vertexbuffer = NULL;
8701 rsurface.modelvertex3f_bufferoffset = 0;
8702 rsurface.modelvertex3f_vertexbuffer = 0;
8703 rsurface.modelvertex3f_bufferoffset = 0;
8704 rsurface.modelsvector3f_vertexbuffer = 0;
8705 rsurface.modelsvector3f_bufferoffset = 0;
8706 rsurface.modeltvector3f_vertexbuffer = 0;
8707 rsurface.modeltvector3f_bufferoffset = 0;
8708 rsurface.modelnormal3f_vertexbuffer = 0;
8709 rsurface.modelnormal3f_bufferoffset = 0;
8711 else if (wantnormals)
8713 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8714 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8715 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8716 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8717 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8718 rsurface.modelsvector3f = NULL;
8719 rsurface.modeltvector3f = NULL;
8720 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8721 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8722 rsurface.modelvertexmesh = NULL;
8723 rsurface.modelvertexmesh_vertexbuffer = NULL;
8724 rsurface.modelvertexmesh_bufferoffset = 0;
8725 rsurface.modelvertex3f_vertexbuffer = NULL;
8726 rsurface.modelvertex3f_bufferoffset = 0;
8727 rsurface.modelvertex3f_vertexbuffer = 0;
8728 rsurface.modelvertex3f_bufferoffset = 0;
8729 rsurface.modelsvector3f_vertexbuffer = 0;
8730 rsurface.modelsvector3f_bufferoffset = 0;
8731 rsurface.modeltvector3f_vertexbuffer = 0;
8732 rsurface.modeltvector3f_bufferoffset = 0;
8733 rsurface.modelnormal3f_vertexbuffer = 0;
8734 rsurface.modelnormal3f_bufferoffset = 0;
8738 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8739 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8740 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8741 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8742 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8743 rsurface.modelsvector3f = NULL;
8744 rsurface.modeltvector3f = NULL;
8745 rsurface.modelnormal3f = NULL;
8746 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8747 rsurface.modelvertexmesh = NULL;
8748 rsurface.modelvertexmesh_vertexbuffer = NULL;
8749 rsurface.modelvertexmesh_bufferoffset = 0;
8750 rsurface.modelvertex3f_vertexbuffer = NULL;
8751 rsurface.modelvertex3f_bufferoffset = 0;
8752 rsurface.modelvertex3f_vertexbuffer = 0;
8753 rsurface.modelvertex3f_bufferoffset = 0;
8754 rsurface.modelsvector3f_vertexbuffer = 0;
8755 rsurface.modelsvector3f_bufferoffset = 0;
8756 rsurface.modeltvector3f_vertexbuffer = 0;
8757 rsurface.modeltvector3f_bufferoffset = 0;
8758 rsurface.modelnormal3f_vertexbuffer = 0;
8759 rsurface.modelnormal3f_bufferoffset = 0;
8761 rsurface.modelgeneratedvertex = true;
8765 if (rsurface.entityskeletaltransform3x4)
8767 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8768 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8769 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8770 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8774 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8775 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8776 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8777 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8779 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8780 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8781 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8782 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8783 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8784 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8785 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8786 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8787 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8788 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8789 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8790 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8791 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8792 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8793 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8794 rsurface.modelgeneratedvertex = false;
8796 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8797 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8798 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8799 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8800 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8801 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8802 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8803 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8804 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8805 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8806 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8807 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8808 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8809 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8810 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8811 rsurface.modelelement3i = model->surfmesh.data_element3i;
8812 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8813 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8814 rsurface.modelelement3s = model->surfmesh.data_element3s;
8815 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8816 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8817 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8818 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8819 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8820 rsurface.modelsurfaces = model->data_surfaces;
8821 rsurface.batchgeneratedvertex = false;
8822 rsurface.batchfirstvertex = 0;
8823 rsurface.batchnumvertices = 0;
8824 rsurface.batchfirsttriangle = 0;
8825 rsurface.batchnumtriangles = 0;
8826 rsurface.batchvertex3f = NULL;
8827 rsurface.batchvertex3f_vertexbuffer = NULL;
8828 rsurface.batchvertex3f_bufferoffset = 0;
8829 rsurface.batchsvector3f = NULL;
8830 rsurface.batchsvector3f_vertexbuffer = NULL;
8831 rsurface.batchsvector3f_bufferoffset = 0;
8832 rsurface.batchtvector3f = NULL;
8833 rsurface.batchtvector3f_vertexbuffer = NULL;
8834 rsurface.batchtvector3f_bufferoffset = 0;
8835 rsurface.batchnormal3f = NULL;
8836 rsurface.batchnormal3f_vertexbuffer = NULL;
8837 rsurface.batchnormal3f_bufferoffset = 0;
8838 rsurface.batchlightmapcolor4f = NULL;
8839 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8840 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8841 rsurface.batchtexcoordtexture2f = NULL;
8842 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8843 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8844 rsurface.batchtexcoordlightmap2f = NULL;
8845 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8846 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8847 rsurface.batchskeletalindex4ub = NULL;
8848 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8849 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8850 rsurface.batchskeletalweight4ub = NULL;
8851 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8852 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8853 rsurface.batchvertexmesh = NULL;
8854 rsurface.batchvertexmesh_vertexbuffer = NULL;
8855 rsurface.batchvertexmesh_bufferoffset = 0;
8856 rsurface.batchelement3i = NULL;
8857 rsurface.batchelement3i_indexbuffer = NULL;
8858 rsurface.batchelement3i_bufferoffset = 0;
8859 rsurface.batchelement3s = NULL;
8860 rsurface.batchelement3s_indexbuffer = NULL;
8861 rsurface.batchelement3s_bufferoffset = 0;
8862 rsurface.passcolor4f = NULL;
8863 rsurface.passcolor4f_vertexbuffer = NULL;
8864 rsurface.passcolor4f_bufferoffset = 0;
8865 rsurface.forcecurrenttextureupdate = false;
8868 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)
8870 rsurface.entity = r_refdef.scene.worldentity;
8871 rsurface.skeleton = NULL;
8872 rsurface.ent_skinnum = 0;
8873 rsurface.ent_qwskin = -1;
8874 rsurface.ent_flags = entflags;
8875 rsurface.shadertime = r_refdef.scene.time - shadertime;
8876 rsurface.modelnumvertices = numvertices;
8877 rsurface.modelnumtriangles = numtriangles;
8878 rsurface.matrix = *matrix;
8879 rsurface.inversematrix = *inversematrix;
8880 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8881 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8882 R_EntityMatrix(&rsurface.matrix);
8883 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8884 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8885 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8886 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8887 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8888 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8889 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8890 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8891 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8892 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8893 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8894 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8895 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);
8896 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8897 rsurface.frameblend[0].lerp = 1;
8898 rsurface.ent_alttextures = false;
8899 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8900 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8901 rsurface.entityskeletaltransform3x4 = NULL;
8902 rsurface.entityskeletaltransform3x4buffer = NULL;
8903 rsurface.entityskeletaltransform3x4offset = 0;
8904 rsurface.entityskeletaltransform3x4size = 0;
8905 rsurface.entityskeletalnumtransforms = 0;
8906 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8907 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8908 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8909 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8912 rsurface.modelvertex3f = (float *)vertex3f;
8913 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8914 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8915 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8917 else if (wantnormals)
8919 rsurface.modelvertex3f = (float *)vertex3f;
8920 rsurface.modelsvector3f = NULL;
8921 rsurface.modeltvector3f = NULL;
8922 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8926 rsurface.modelvertex3f = (float *)vertex3f;
8927 rsurface.modelsvector3f = NULL;
8928 rsurface.modeltvector3f = NULL;
8929 rsurface.modelnormal3f = NULL;
8931 rsurface.modelvertexmesh = NULL;
8932 rsurface.modelvertexmesh_vertexbuffer = NULL;
8933 rsurface.modelvertexmesh_bufferoffset = 0;
8934 rsurface.modelvertex3f_vertexbuffer = 0;
8935 rsurface.modelvertex3f_bufferoffset = 0;
8936 rsurface.modelsvector3f_vertexbuffer = 0;
8937 rsurface.modelsvector3f_bufferoffset = 0;
8938 rsurface.modeltvector3f_vertexbuffer = 0;
8939 rsurface.modeltvector3f_bufferoffset = 0;
8940 rsurface.modelnormal3f_vertexbuffer = 0;
8941 rsurface.modelnormal3f_bufferoffset = 0;
8942 rsurface.modelgeneratedvertex = true;
8943 rsurface.modellightmapcolor4f = (float *)color4f;
8944 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8945 rsurface.modellightmapcolor4f_bufferoffset = 0;
8946 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8947 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8948 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8949 rsurface.modeltexcoordlightmap2f = NULL;
8950 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8951 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8952 rsurface.modelskeletalindex4ub = NULL;
8953 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8954 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8955 rsurface.modelskeletalweight4ub = NULL;
8956 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8957 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8958 rsurface.modelelement3i = (int *)element3i;
8959 rsurface.modelelement3i_indexbuffer = NULL;
8960 rsurface.modelelement3i_bufferoffset = 0;
8961 rsurface.modelelement3s = (unsigned short *)element3s;
8962 rsurface.modelelement3s_indexbuffer = NULL;
8963 rsurface.modelelement3s_bufferoffset = 0;
8964 rsurface.modellightmapoffsets = NULL;
8965 rsurface.modelsurfaces = NULL;
8966 rsurface.batchgeneratedvertex = false;
8967 rsurface.batchfirstvertex = 0;
8968 rsurface.batchnumvertices = 0;
8969 rsurface.batchfirsttriangle = 0;
8970 rsurface.batchnumtriangles = 0;
8971 rsurface.batchvertex3f = NULL;
8972 rsurface.batchvertex3f_vertexbuffer = NULL;
8973 rsurface.batchvertex3f_bufferoffset = 0;
8974 rsurface.batchsvector3f = NULL;
8975 rsurface.batchsvector3f_vertexbuffer = NULL;
8976 rsurface.batchsvector3f_bufferoffset = 0;
8977 rsurface.batchtvector3f = NULL;
8978 rsurface.batchtvector3f_vertexbuffer = NULL;
8979 rsurface.batchtvector3f_bufferoffset = 0;
8980 rsurface.batchnormal3f = NULL;
8981 rsurface.batchnormal3f_vertexbuffer = NULL;
8982 rsurface.batchnormal3f_bufferoffset = 0;
8983 rsurface.batchlightmapcolor4f = NULL;
8984 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8985 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8986 rsurface.batchtexcoordtexture2f = NULL;
8987 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8988 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8989 rsurface.batchtexcoordlightmap2f = NULL;
8990 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8991 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8992 rsurface.batchskeletalindex4ub = NULL;
8993 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8994 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8995 rsurface.batchskeletalweight4ub = NULL;
8996 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8997 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8998 rsurface.batchvertexmesh = NULL;
8999 rsurface.batchvertexmesh_vertexbuffer = NULL;
9000 rsurface.batchvertexmesh_bufferoffset = 0;
9001 rsurface.batchelement3i = NULL;
9002 rsurface.batchelement3i_indexbuffer = NULL;
9003 rsurface.batchelement3i_bufferoffset = 0;
9004 rsurface.batchelement3s = NULL;
9005 rsurface.batchelement3s_indexbuffer = NULL;
9006 rsurface.batchelement3s_bufferoffset = 0;
9007 rsurface.passcolor4f = NULL;
9008 rsurface.passcolor4f_vertexbuffer = NULL;
9009 rsurface.passcolor4f_bufferoffset = 0;
9010 rsurface.forcecurrenttextureupdate = true;
9012 if (rsurface.modelnumvertices && rsurface.modelelement3i)
9014 if ((wantnormals || wanttangents) && !normal3f)
9016 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9017 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9019 if (wanttangents && !svector3f)
9021 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9022 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9023 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9028 float RSurf_FogPoint(const float *v)
9030 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9031 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9032 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9033 float FogHeightFade = r_refdef.fogheightfade;
9035 unsigned int fogmasktableindex;
9036 if (r_refdef.fogplaneviewabove)
9037 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9039 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9040 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9041 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9044 float RSurf_FogVertex(const float *v)
9046 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9047 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9048 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9049 float FogHeightFade = rsurface.fogheightfade;
9051 unsigned int fogmasktableindex;
9052 if (r_refdef.fogplaneviewabove)
9053 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9055 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9056 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9057 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9060 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9063 for (i = 0;i < numelements;i++)
9064 outelement3i[i] = inelement3i[i] + adjust;
9067 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9068 extern cvar_t gl_vbo;
9069 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9077 int surfacefirsttriangle;
9078 int surfacenumtriangles;
9079 int surfacefirstvertex;
9080 int surfaceendvertex;
9081 int surfacenumvertices;
9082 int batchnumsurfaces = texturenumsurfaces;
9083 int batchnumvertices;
9084 int batchnumtriangles;
9088 qboolean dynamicvertex;
9091 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9094 q3shaderinfo_deform_t *deform;
9095 const msurface_t *surface, *firstsurface;
9096 r_vertexmesh_t *vertexmesh;
9097 if (!texturenumsurfaces)
9099 // find vertex range of this surface batch
9101 firstsurface = texturesurfacelist[0];
9102 firsttriangle = firstsurface->num_firsttriangle;
9103 batchnumvertices = 0;
9104 batchnumtriangles = 0;
9105 firstvertex = endvertex = firstsurface->num_firstvertex;
9106 for (i = 0;i < texturenumsurfaces;i++)
9108 surface = texturesurfacelist[i];
9109 if (surface != firstsurface + i)
9111 surfacefirstvertex = surface->num_firstvertex;
9112 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9113 surfacenumvertices = surface->num_vertices;
9114 surfacenumtriangles = surface->num_triangles;
9115 if (firstvertex > surfacefirstvertex)
9116 firstvertex = surfacefirstvertex;
9117 if (endvertex < surfaceendvertex)
9118 endvertex = surfaceendvertex;
9119 batchnumvertices += surfacenumvertices;
9120 batchnumtriangles += surfacenumtriangles;
9123 r_refdef.stats[r_stat_batch_batches]++;
9125 r_refdef.stats[r_stat_batch_withgaps]++;
9126 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9127 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9128 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9130 // we now know the vertex range used, and if there are any gaps in it
9131 rsurface.batchfirstvertex = firstvertex;
9132 rsurface.batchnumvertices = endvertex - firstvertex;
9133 rsurface.batchfirsttriangle = firsttriangle;
9134 rsurface.batchnumtriangles = batchnumtriangles;
9136 // this variable holds flags for which properties have been updated that
9137 // may require regenerating vertexmesh array...
9140 // check if any dynamic vertex processing must occur
9141 dynamicvertex = false;
9143 // a cvar to force the dynamic vertex path to be taken, for debugging
9144 if (r_batch_debugdynamicvertexpath.integer)
9148 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9149 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9150 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9151 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9153 dynamicvertex = true;
9156 // if there is a chance of animated vertex colors, it's a dynamic batch
9157 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9161 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9162 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9163 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9164 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9166 dynamicvertex = true;
9167 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9170 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9172 switch (deform->deform)
9175 case Q3DEFORM_PROJECTIONSHADOW:
9176 case Q3DEFORM_TEXT0:
9177 case Q3DEFORM_TEXT1:
9178 case Q3DEFORM_TEXT2:
9179 case Q3DEFORM_TEXT3:
9180 case Q3DEFORM_TEXT4:
9181 case Q3DEFORM_TEXT5:
9182 case Q3DEFORM_TEXT6:
9183 case Q3DEFORM_TEXT7:
9186 case Q3DEFORM_AUTOSPRITE:
9189 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9190 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9191 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9192 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9194 dynamicvertex = true;
9195 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9196 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9198 case Q3DEFORM_AUTOSPRITE2:
9201 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9202 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9203 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9204 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9206 dynamicvertex = true;
9207 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9208 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9210 case Q3DEFORM_NORMAL:
9213 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9214 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9215 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9216 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9218 dynamicvertex = true;
9219 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9220 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9223 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9224 break; // if wavefunc is a nop, ignore this transform
9227 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9228 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9229 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9230 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9232 dynamicvertex = true;
9233 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9234 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9236 case Q3DEFORM_BULGE:
9239 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9240 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9241 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9242 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9244 dynamicvertex = true;
9245 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9246 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9249 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9250 break; // if wavefunc is a nop, ignore this transform
9253 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9254 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9255 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9256 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9258 dynamicvertex = true;
9259 batchneed |= BATCHNEED_ARRAY_VERTEX;
9260 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9264 switch(rsurface.texture->tcgen.tcgen)
9267 case Q3TCGEN_TEXTURE:
9269 case Q3TCGEN_LIGHTMAP:
9272 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9273 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9274 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9275 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9277 dynamicvertex = true;
9278 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9279 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9281 case Q3TCGEN_VECTOR:
9284 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9285 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9286 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9287 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9289 dynamicvertex = true;
9290 batchneed |= BATCHNEED_ARRAY_VERTEX;
9291 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9293 case Q3TCGEN_ENVIRONMENT:
9296 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9297 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9298 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9299 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9301 dynamicvertex = true;
9302 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9303 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9306 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9310 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9311 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9312 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9313 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9315 dynamicvertex = true;
9316 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9317 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9320 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9324 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9325 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9326 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9327 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9329 dynamicvertex = true;
9330 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9333 // when the model data has no vertex buffer (dynamic mesh), we need to
9335 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9336 batchneed |= BATCHNEED_NOGAPS;
9338 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9339 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9340 // we ensure this by treating the vertex batch as dynamic...
9341 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9345 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9346 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9347 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9348 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9350 dynamicvertex = true;
9355 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9356 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9357 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9358 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9359 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9360 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9361 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9362 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9365 // if needsupdate, we have to do a dynamic vertex batch for sure
9366 if (needsupdate & batchneed)
9370 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9371 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9372 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9373 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9375 dynamicvertex = true;
9378 // see if we need to build vertexmesh from arrays
9379 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9383 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9384 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9385 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9386 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9388 dynamicvertex = true;
9391 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9392 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9393 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9395 rsurface.batchvertex3f = rsurface.modelvertex3f;
9396 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9397 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9398 rsurface.batchsvector3f = rsurface.modelsvector3f;
9399 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9400 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9401 rsurface.batchtvector3f = rsurface.modeltvector3f;
9402 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9403 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9404 rsurface.batchnormal3f = rsurface.modelnormal3f;
9405 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9406 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9407 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9408 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9409 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9410 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9411 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9412 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9413 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9414 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9415 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9416 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9417 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9418 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9419 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9420 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9421 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9422 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9423 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9424 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9425 rsurface.batchelement3i = rsurface.modelelement3i;
9426 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9427 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9428 rsurface.batchelement3s = rsurface.modelelement3s;
9429 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9430 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9431 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9432 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9433 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9434 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9435 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9437 // if any dynamic vertex processing has to occur in software, we copy the
9438 // entire surface list together before processing to rebase the vertices
9439 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9441 // if any gaps exist and we do not have a static vertex buffer, we have to
9442 // copy the surface list together to avoid wasting upload bandwidth on the
9443 // vertices in the gaps.
9445 // if gaps exist and we have a static vertex buffer, we can choose whether
9446 // to combine the index buffer ranges into one dynamic index buffer or
9447 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9449 // in many cases the batch is reduced to one draw call.
9451 rsurface.batchmultidraw = false;
9452 rsurface.batchmultidrawnumsurfaces = 0;
9453 rsurface.batchmultidrawsurfacelist = NULL;
9457 // static vertex data, just set pointers...
9458 rsurface.batchgeneratedvertex = false;
9459 // if there are gaps, we want to build a combined index buffer,
9460 // otherwise use the original static buffer with an appropriate offset
9463 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9464 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9465 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9466 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9467 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9469 rsurface.batchmultidraw = true;
9470 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9471 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9474 // build a new triangle elements array for this batch
9475 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9476 rsurface.batchfirsttriangle = 0;
9478 for (i = 0;i < texturenumsurfaces;i++)
9480 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9481 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9482 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9483 numtriangles += surfacenumtriangles;
9485 rsurface.batchelement3i_indexbuffer = NULL;
9486 rsurface.batchelement3i_bufferoffset = 0;
9487 rsurface.batchelement3s = NULL;
9488 rsurface.batchelement3s_indexbuffer = NULL;
9489 rsurface.batchelement3s_bufferoffset = 0;
9490 if (endvertex <= 65536)
9492 // make a 16bit (unsigned short) index array if possible
9493 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9494 for (i = 0;i < numtriangles*3;i++)
9495 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9497 // upload buffer data for the copytriangles batch
9498 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9500 if (rsurface.batchelement3s)
9501 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9502 else if (rsurface.batchelement3i)
9503 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9508 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9509 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9510 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9511 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9516 // something needs software processing, do it for real...
9517 // we only directly handle separate array data in this case and then
9518 // generate interleaved data if needed...
9519 rsurface.batchgeneratedvertex = true;
9520 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9521 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9522 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9523 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9525 // now copy the vertex data into a combined array and make an index array
9526 // (this is what Quake3 does all the time)
9527 // we also apply any skeletal animation here that would have been done in
9528 // the vertex shader, because most of the dynamic vertex animation cases
9529 // need actual vertex positions and normals
9530 //if (dynamicvertex)
9532 rsurface.batchvertexmesh = NULL;
9533 rsurface.batchvertexmesh_vertexbuffer = NULL;
9534 rsurface.batchvertexmesh_bufferoffset = 0;
9535 rsurface.batchvertex3f = NULL;
9536 rsurface.batchvertex3f_vertexbuffer = NULL;
9537 rsurface.batchvertex3f_bufferoffset = 0;
9538 rsurface.batchsvector3f = NULL;
9539 rsurface.batchsvector3f_vertexbuffer = NULL;
9540 rsurface.batchsvector3f_bufferoffset = 0;
9541 rsurface.batchtvector3f = NULL;
9542 rsurface.batchtvector3f_vertexbuffer = NULL;
9543 rsurface.batchtvector3f_bufferoffset = 0;
9544 rsurface.batchnormal3f = NULL;
9545 rsurface.batchnormal3f_vertexbuffer = NULL;
9546 rsurface.batchnormal3f_bufferoffset = 0;
9547 rsurface.batchlightmapcolor4f = NULL;
9548 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9549 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9550 rsurface.batchtexcoordtexture2f = NULL;
9551 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9552 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9553 rsurface.batchtexcoordlightmap2f = NULL;
9554 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9555 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9556 rsurface.batchskeletalindex4ub = NULL;
9557 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9558 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9559 rsurface.batchskeletalweight4ub = NULL;
9560 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9561 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9562 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9563 rsurface.batchelement3i_indexbuffer = NULL;
9564 rsurface.batchelement3i_bufferoffset = 0;
9565 rsurface.batchelement3s = NULL;
9566 rsurface.batchelement3s_indexbuffer = NULL;
9567 rsurface.batchelement3s_bufferoffset = 0;
9568 rsurface.batchskeletaltransform3x4buffer = NULL;
9569 rsurface.batchskeletaltransform3x4offset = 0;
9570 rsurface.batchskeletaltransform3x4size = 0;
9571 // we'll only be setting up certain arrays as needed
9572 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9573 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9574 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9575 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9576 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9577 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9578 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9580 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9581 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9583 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9584 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9585 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9586 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9587 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9588 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9589 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9591 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9592 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9596 for (i = 0;i < texturenumsurfaces;i++)
9598 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9599 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9600 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9601 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9602 // copy only the data requested
9603 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9604 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9605 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9607 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9609 if (rsurface.batchvertex3f)
9610 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9612 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9614 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9616 if (rsurface.modelnormal3f)
9617 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9619 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9621 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9623 if (rsurface.modelsvector3f)
9625 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9626 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9630 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9631 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9634 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9636 if (rsurface.modellightmapcolor4f)
9637 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9639 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9641 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9643 if (rsurface.modeltexcoordtexture2f)
9644 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9646 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9648 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9650 if (rsurface.modeltexcoordlightmap2f)
9651 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9653 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9655 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9657 if (rsurface.modelskeletalindex4ub)
9659 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9660 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9664 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9665 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9666 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9667 for (j = 0;j < surfacenumvertices;j++)
9672 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9673 numvertices += surfacenumvertices;
9674 numtriangles += surfacenumtriangles;
9677 // generate a 16bit index array as well if possible
9678 // (in general, dynamic batches fit)
9679 if (numvertices <= 65536)
9681 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9682 for (i = 0;i < numtriangles*3;i++)
9683 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9686 // since we've copied everything, the batch now starts at 0
9687 rsurface.batchfirstvertex = 0;
9688 rsurface.batchnumvertices = batchnumvertices;
9689 rsurface.batchfirsttriangle = 0;
9690 rsurface.batchnumtriangles = batchnumtriangles;
9693 // apply skeletal animation that would have been done in the vertex shader
9694 if (rsurface.batchskeletaltransform3x4)
9696 const unsigned char *si;
9697 const unsigned char *sw;
9699 const float *b = rsurface.batchskeletaltransform3x4;
9700 float *vp, *vs, *vt, *vn;
9702 float m[3][4], n[3][4];
9703 float tp[3], ts[3], tt[3], tn[3];
9704 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9705 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9706 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9707 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9708 si = rsurface.batchskeletalindex4ub;
9709 sw = rsurface.batchskeletalweight4ub;
9710 vp = rsurface.batchvertex3f;
9711 vs = rsurface.batchsvector3f;
9712 vt = rsurface.batchtvector3f;
9713 vn = rsurface.batchnormal3f;
9714 memset(m[0], 0, sizeof(m));
9715 memset(n[0], 0, sizeof(n));
9716 for (i = 0;i < batchnumvertices;i++)
9718 t[0] = b + si[0]*12;
9721 // common case - only one matrix
9735 else if (sw[2] + sw[3])
9738 t[1] = b + si[1]*12;
9739 t[2] = b + si[2]*12;
9740 t[3] = b + si[3]*12;
9741 w[0] = sw[0] * (1.0f / 255.0f);
9742 w[1] = sw[1] * (1.0f / 255.0f);
9743 w[2] = sw[2] * (1.0f / 255.0f);
9744 w[3] = sw[3] * (1.0f / 255.0f);
9745 // blend the matrices
9746 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9747 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9748 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9749 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9750 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9751 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9752 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9753 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9754 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9755 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9756 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9757 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9762 t[1] = b + si[1]*12;
9763 w[0] = sw[0] * (1.0f / 255.0f);
9764 w[1] = sw[1] * (1.0f / 255.0f);
9765 // blend the matrices
9766 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9767 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9768 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9769 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9770 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9771 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9772 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9773 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9774 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9775 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9776 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9777 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9781 // modify the vertex
9783 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9784 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9785 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9789 // the normal transformation matrix is a set of cross products...
9790 CrossProduct(m[1], m[2], n[0]);
9791 CrossProduct(m[2], m[0], n[1]);
9792 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9794 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9795 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9796 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9797 VectorNormalize(vn);
9802 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9803 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9804 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9805 VectorNormalize(vs);
9808 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9809 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9810 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9811 VectorNormalize(vt);
9816 rsurface.batchskeletaltransform3x4 = NULL;
9817 rsurface.batchskeletalnumtransforms = 0;
9820 // q1bsp surfaces rendered in vertex color mode have to have colors
9821 // calculated based on lightstyles
9822 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9824 // generate color arrays for the surfaces in this list
9829 const unsigned char *lm;
9830 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9831 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9832 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9834 for (i = 0;i < texturenumsurfaces;i++)
9836 surface = texturesurfacelist[i];
9837 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9838 surfacenumvertices = surface->num_vertices;
9839 if (surface->lightmapinfo->samples)
9841 for (j = 0;j < surfacenumvertices;j++)
9843 lm = surface->lightmapinfo->samples + offsets[j];
9844 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9845 VectorScale(lm, scale, c);
9846 if (surface->lightmapinfo->styles[1] != 255)
9848 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9850 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9851 VectorMA(c, scale, lm, c);
9852 if (surface->lightmapinfo->styles[2] != 255)
9855 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9856 VectorMA(c, scale, lm, c);
9857 if (surface->lightmapinfo->styles[3] != 255)
9860 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9861 VectorMA(c, scale, lm, c);
9868 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);
9874 for (j = 0;j < surfacenumvertices;j++)
9876 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9883 // if vertices are deformed (sprite flares and things in maps, possibly
9884 // water waves, bulges and other deformations), modify the copied vertices
9886 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9889 switch (deform->deform)
9892 case Q3DEFORM_PROJECTIONSHADOW:
9893 case Q3DEFORM_TEXT0:
9894 case Q3DEFORM_TEXT1:
9895 case Q3DEFORM_TEXT2:
9896 case Q3DEFORM_TEXT3:
9897 case Q3DEFORM_TEXT4:
9898 case Q3DEFORM_TEXT5:
9899 case Q3DEFORM_TEXT6:
9900 case Q3DEFORM_TEXT7:
9903 case Q3DEFORM_AUTOSPRITE:
9904 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9905 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9906 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9907 VectorNormalize(newforward);
9908 VectorNormalize(newright);
9909 VectorNormalize(newup);
9910 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9911 // rsurface.batchvertex3f_vertexbuffer = NULL;
9912 // rsurface.batchvertex3f_bufferoffset = 0;
9913 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9914 // rsurface.batchsvector3f_vertexbuffer = NULL;
9915 // rsurface.batchsvector3f_bufferoffset = 0;
9916 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9917 // rsurface.batchtvector3f_vertexbuffer = NULL;
9918 // rsurface.batchtvector3f_bufferoffset = 0;
9919 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9920 // rsurface.batchnormal3f_vertexbuffer = NULL;
9921 // rsurface.batchnormal3f_bufferoffset = 0;
9922 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9923 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9924 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9925 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9926 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);
9927 // a single autosprite surface can contain multiple sprites...
9928 for (j = 0;j < batchnumvertices - 3;j += 4)
9930 VectorClear(center);
9931 for (i = 0;i < 4;i++)
9932 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9933 VectorScale(center, 0.25f, center);
9934 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9935 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9936 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9937 for (i = 0;i < 4;i++)
9939 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9940 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9943 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9944 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9945 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);
9947 case Q3DEFORM_AUTOSPRITE2:
9948 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9949 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9950 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9951 VectorNormalize(newforward);
9952 VectorNormalize(newright);
9953 VectorNormalize(newup);
9954 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9955 // rsurface.batchvertex3f_vertexbuffer = NULL;
9956 // rsurface.batchvertex3f_bufferoffset = 0;
9958 const float *v1, *v2;
9968 memset(shortest, 0, sizeof(shortest));
9969 // a single autosprite surface can contain multiple sprites...
9970 for (j = 0;j < batchnumvertices - 3;j += 4)
9972 VectorClear(center);
9973 for (i = 0;i < 4;i++)
9974 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9975 VectorScale(center, 0.25f, center);
9976 // find the two shortest edges, then use them to define the
9977 // axis vectors for rotating around the central axis
9978 for (i = 0;i < 6;i++)
9980 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9981 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9982 l = VectorDistance2(v1, v2);
9983 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9985 l += (1.0f / 1024.0f);
9986 if (shortest[0].length2 > l || i == 0)
9988 shortest[1] = shortest[0];
9989 shortest[0].length2 = l;
9990 shortest[0].v1 = v1;
9991 shortest[0].v2 = v2;
9993 else if (shortest[1].length2 > l || i == 1)
9995 shortest[1].length2 = l;
9996 shortest[1].v1 = v1;
9997 shortest[1].v2 = v2;
10000 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10001 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10002 // this calculates the right vector from the shortest edge
10003 // and the up vector from the edge midpoints
10004 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10005 VectorNormalize(right);
10006 VectorSubtract(end, start, up);
10007 VectorNormalize(up);
10008 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10009 VectorSubtract(rsurface.localvieworigin, center, forward);
10010 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10011 VectorNegate(forward, forward);
10012 VectorReflect(forward, 0, up, forward);
10013 VectorNormalize(forward);
10014 CrossProduct(up, forward, newright);
10015 VectorNormalize(newright);
10016 // rotate the quad around the up axis vector, this is made
10017 // especially easy by the fact we know the quad is flat,
10018 // so we only have to subtract the center position and
10019 // measure distance along the right vector, and then
10020 // multiply that by the newright vector and add back the
10022 // we also need to subtract the old position to undo the
10023 // displacement from the center, which we do with a
10024 // DotProduct, the subtraction/addition of center is also
10025 // optimized into DotProducts here
10026 l = DotProduct(right, center);
10027 for (i = 0;i < 4;i++)
10029 v1 = rsurface.batchvertex3f + 3*(j+i);
10030 f = DotProduct(right, v1) - l;
10031 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10035 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10037 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10038 // rsurface.batchnormal3f_vertexbuffer = NULL;
10039 // rsurface.batchnormal3f_bufferoffset = 0;
10040 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10042 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10044 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10045 // rsurface.batchsvector3f_vertexbuffer = NULL;
10046 // rsurface.batchsvector3f_bufferoffset = 0;
10047 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10048 // rsurface.batchtvector3f_vertexbuffer = NULL;
10049 // rsurface.batchtvector3f_bufferoffset = 0;
10050 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);
10053 case Q3DEFORM_NORMAL:
10054 // deform the normals to make reflections wavey
10055 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10056 rsurface.batchnormal3f_vertexbuffer = NULL;
10057 rsurface.batchnormal3f_bufferoffset = 0;
10058 for (j = 0;j < batchnumvertices;j++)
10061 float *normal = rsurface.batchnormal3f + 3*j;
10062 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10063 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10064 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10065 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10066 VectorNormalize(normal);
10068 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10070 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10071 // rsurface.batchsvector3f_vertexbuffer = NULL;
10072 // rsurface.batchsvector3f_bufferoffset = 0;
10073 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10074 // rsurface.batchtvector3f_vertexbuffer = NULL;
10075 // rsurface.batchtvector3f_bufferoffset = 0;
10076 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);
10079 case Q3DEFORM_WAVE:
10080 // deform vertex array to make wavey water and flags and such
10081 waveparms[0] = deform->waveparms[0];
10082 waveparms[1] = deform->waveparms[1];
10083 waveparms[2] = deform->waveparms[2];
10084 waveparms[3] = deform->waveparms[3];
10085 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10086 break; // if wavefunc is a nop, don't make a dynamic vertex array
10087 // this is how a divisor of vertex influence on deformation
10088 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10089 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10090 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10091 // rsurface.batchvertex3f_vertexbuffer = NULL;
10092 // rsurface.batchvertex3f_bufferoffset = 0;
10093 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10094 // rsurface.batchnormal3f_vertexbuffer = NULL;
10095 // rsurface.batchnormal3f_bufferoffset = 0;
10096 for (j = 0;j < batchnumvertices;j++)
10098 // if the wavefunc depends on time, evaluate it per-vertex
10101 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10102 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10104 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10106 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10107 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10108 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10110 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10111 // rsurface.batchsvector3f_vertexbuffer = NULL;
10112 // rsurface.batchsvector3f_bufferoffset = 0;
10113 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10114 // rsurface.batchtvector3f_vertexbuffer = NULL;
10115 // rsurface.batchtvector3f_bufferoffset = 0;
10116 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);
10119 case Q3DEFORM_BULGE:
10120 // deform vertex array to make the surface have moving bulges
10121 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10122 // rsurface.batchvertex3f_vertexbuffer = NULL;
10123 // rsurface.batchvertex3f_bufferoffset = 0;
10124 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10125 // rsurface.batchnormal3f_vertexbuffer = NULL;
10126 // rsurface.batchnormal3f_bufferoffset = 0;
10127 for (j = 0;j < batchnumvertices;j++)
10129 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10130 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10132 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10133 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10134 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10136 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10137 // rsurface.batchsvector3f_vertexbuffer = NULL;
10138 // rsurface.batchsvector3f_bufferoffset = 0;
10139 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10140 // rsurface.batchtvector3f_vertexbuffer = NULL;
10141 // rsurface.batchtvector3f_bufferoffset = 0;
10142 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);
10145 case Q3DEFORM_MOVE:
10146 // deform vertex array
10147 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10148 break; // if wavefunc is a nop, don't make a dynamic vertex array
10149 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10150 VectorScale(deform->parms, scale, waveparms);
10151 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10152 // rsurface.batchvertex3f_vertexbuffer = NULL;
10153 // rsurface.batchvertex3f_bufferoffset = 0;
10154 for (j = 0;j < batchnumvertices;j++)
10155 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10160 if (rsurface.batchtexcoordtexture2f)
10162 // generate texcoords based on the chosen texcoord source
10163 switch(rsurface.texture->tcgen.tcgen)
10166 case Q3TCGEN_TEXTURE:
10168 case Q3TCGEN_LIGHTMAP:
10169 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10170 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10171 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10172 if (rsurface.batchtexcoordlightmap2f)
10173 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10175 case Q3TCGEN_VECTOR:
10176 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10177 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10178 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10179 for (j = 0;j < batchnumvertices;j++)
10181 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10182 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10185 case Q3TCGEN_ENVIRONMENT:
10186 // make environment reflections using a spheremap
10187 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10188 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10189 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10190 for (j = 0;j < batchnumvertices;j++)
10192 // identical to Q3A's method, but executed in worldspace so
10193 // carried models can be shiny too
10195 float viewer[3], d, reflected[3], worldreflected[3];
10197 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10198 // VectorNormalize(viewer);
10200 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10202 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10203 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10204 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10205 // note: this is proportinal to viewer, so we can normalize later
10207 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10208 VectorNormalize(worldreflected);
10210 // note: this sphere map only uses world x and z!
10211 // so positive and negative y will LOOK THE SAME.
10212 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10213 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10217 // the only tcmod that needs software vertex processing is turbulent, so
10218 // check for it here and apply the changes if needed
10219 // and we only support that as the first one
10220 // (handling a mixture of turbulent and other tcmods would be problematic
10221 // without punting it entirely to a software path)
10222 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10224 amplitude = rsurface.texture->tcmods[0].parms[1];
10225 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10226 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10227 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10228 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10229 for (j = 0;j < batchnumvertices;j++)
10231 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);
10232 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10237 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10239 // convert the modified arrays to vertex structs
10240 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10241 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10242 // rsurface.batchvertexmesh_bufferoffset = 0;
10243 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10244 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10245 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10246 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10247 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10248 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10249 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10251 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10253 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10254 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10257 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10258 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10259 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10260 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10261 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10262 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10263 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10264 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10265 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10266 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10268 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10270 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10271 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10276 // upload buffer data for the dynamic batch
10277 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10279 if (rsurface.batchvertexmesh)
10280 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10283 if (rsurface.batchvertex3f)
10284 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10285 if (rsurface.batchsvector3f)
10286 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10287 if (rsurface.batchtvector3f)
10288 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10289 if (rsurface.batchnormal3f)
10290 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10291 if (rsurface.batchlightmapcolor4f)
10292 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10293 if (rsurface.batchtexcoordtexture2f)
10294 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10295 if (rsurface.batchtexcoordlightmap2f)
10296 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10297 if (rsurface.batchskeletalindex4ub)
10298 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10299 if (rsurface.batchskeletalweight4ub)
10300 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10302 if (rsurface.batchelement3s)
10303 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10304 else if (rsurface.batchelement3i)
10305 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10309 void RSurf_DrawBatch(void)
10311 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10312 // through the pipeline, killing it earlier in the pipeline would have
10313 // per-surface overhead rather than per-batch overhead, so it's best to
10314 // reject it here, before it hits glDraw.
10315 if (rsurface.batchnumtriangles == 0)
10318 // batch debugging code
10319 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10325 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10326 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10329 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10331 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10333 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10334 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);
10341 if (rsurface.batchmultidraw)
10343 // issue multiple draws rather than copying index data
10344 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10345 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10346 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10347 for (i = 0;i < numsurfaces;)
10349 // combine consecutive surfaces as one draw
10350 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10351 if (surfacelist[j] != surfacelist[k] + 1)
10353 firstvertex = surfacelist[i]->num_firstvertex;
10354 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10355 firsttriangle = surfacelist[i]->num_firsttriangle;
10356 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10357 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);
10363 // there is only one consecutive run of index data (may have been combined)
10364 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);
10368 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10370 // pick the closest matching water plane
10371 int planeindex, vertexindex, bestplaneindex = -1;
10375 r_waterstate_waterplane_t *p;
10376 qboolean prepared = false;
10378 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10380 if(p->camera_entity != rsurface.texture->camera_entity)
10385 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10387 if(rsurface.batchnumvertices == 0)
10390 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10392 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10393 d += fabs(PlaneDiff(vert, &p->plane));
10395 if (bestd > d || bestplaneindex < 0)
10398 bestplaneindex = planeindex;
10401 return bestplaneindex;
10402 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10403 // this situation though, as it might be better to render single larger
10404 // batches with useless stuff (backface culled for example) than to
10405 // render multiple smaller batches
10408 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10411 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10412 rsurface.passcolor4f_vertexbuffer = 0;
10413 rsurface.passcolor4f_bufferoffset = 0;
10414 for (i = 0;i < rsurface.batchnumvertices;i++)
10415 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10418 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10425 if (rsurface.passcolor4f)
10427 // generate color arrays
10428 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10429 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10430 rsurface.passcolor4f_vertexbuffer = 0;
10431 rsurface.passcolor4f_bufferoffset = 0;
10432 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)
10434 f = RSurf_FogVertex(v);
10443 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10444 rsurface.passcolor4f_vertexbuffer = 0;
10445 rsurface.passcolor4f_bufferoffset = 0;
10446 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10448 f = RSurf_FogVertex(v);
10457 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10464 if (!rsurface.passcolor4f)
10466 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10467 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10468 rsurface.passcolor4f_vertexbuffer = 0;
10469 rsurface.passcolor4f_bufferoffset = 0;
10470 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)
10472 f = RSurf_FogVertex(v);
10473 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10474 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10475 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10480 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10485 if (!rsurface.passcolor4f)
10487 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10488 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10489 rsurface.passcolor4f_vertexbuffer = 0;
10490 rsurface.passcolor4f_bufferoffset = 0;
10491 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10500 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10505 if (!rsurface.passcolor4f)
10507 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10508 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10509 rsurface.passcolor4f_vertexbuffer = 0;
10510 rsurface.passcolor4f_bufferoffset = 0;
10511 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10513 c2[0] = c[0] + r_refdef.scene.ambient;
10514 c2[1] = c[1] + r_refdef.scene.ambient;
10515 c2[2] = c[2] + r_refdef.scene.ambient;
10520 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10523 rsurface.passcolor4f = NULL;
10524 rsurface.passcolor4f_vertexbuffer = 0;
10525 rsurface.passcolor4f_bufferoffset = 0;
10526 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10527 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10528 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10529 GL_Color(r, g, b, a);
10530 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10531 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10532 R_Mesh_TexMatrix(0, NULL);
10536 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10538 // TODO: optimize applyfog && applycolor case
10539 // just apply fog if necessary, and tint the fog color array if necessary
10540 rsurface.passcolor4f = NULL;
10541 rsurface.passcolor4f_vertexbuffer = 0;
10542 rsurface.passcolor4f_bufferoffset = 0;
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_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10553 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10554 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10555 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10556 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10557 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10558 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10559 GL_Color(r, g, b, a);
10563 static void RSurf_DrawBatch_GL11_ClampColor(void)
10568 if (!rsurface.passcolor4f)
10570 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10572 c2[0] = bound(0.0f, c1[0], 1.0f);
10573 c2[1] = bound(0.0f, c1[1], 1.0f);
10574 c2[2] = bound(0.0f, c1[2], 1.0f);
10575 c2[3] = bound(0.0f, c1[3], 1.0f);
10579 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10589 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10590 rsurface.passcolor4f_vertexbuffer = 0;
10591 rsurface.passcolor4f_bufferoffset = 0;
10592 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10594 f = -DotProduct(r_refdef.view.forward, n);
10596 f = f * 0.85 + 0.15; // work around so stuff won't get black
10597 f *= r_refdef.lightmapintensity;
10598 Vector4Set(c, f, f, f, 1);
10602 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10604 RSurf_DrawBatch_GL11_ApplyFakeLight();
10605 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10606 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10607 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10608 GL_Color(r, g, b, a);
10612 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10620 vec3_t ambientcolor;
10621 vec3_t diffusecolor;
10625 VectorCopy(rsurface.modellight_lightdir, lightdir);
10626 f = 0.5f * r_refdef.lightmapintensity;
10627 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10628 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10629 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10630 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10631 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10632 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10634 if (VectorLength2(diffusecolor) > 0)
10636 // q3-style directional shading
10637 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10638 rsurface.passcolor4f_vertexbuffer = 0;
10639 rsurface.passcolor4f_bufferoffset = 0;
10640 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)
10642 if ((f = DotProduct(n, lightdir)) > 0)
10643 VectorMA(ambientcolor, f, diffusecolor, c);
10645 VectorCopy(ambientcolor, c);
10652 *applycolor = false;
10656 *r = ambientcolor[0];
10657 *g = ambientcolor[1];
10658 *b = ambientcolor[2];
10659 rsurface.passcolor4f = NULL;
10660 rsurface.passcolor4f_vertexbuffer = 0;
10661 rsurface.passcolor4f_bufferoffset = 0;
10665 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10667 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10668 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10669 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10670 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10671 GL_Color(r, g, b, a);
10675 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10683 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10684 rsurface.passcolor4f_vertexbuffer = 0;
10685 rsurface.passcolor4f_bufferoffset = 0;
10687 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10689 f = 1 - RSurf_FogVertex(v);
10697 void RSurf_SetupDepthAndCulling(void)
10699 // submodels are biased to avoid z-fighting with world surfaces that they
10700 // may be exactly overlapping (avoids z-fighting artifacts on certain
10701 // doors and things in Quake maps)
10702 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10703 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10704 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10705 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10708 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10710 // transparent sky would be ridiculous
10711 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10713 R_SetupShader_Generic_NoTexture(false, false);
10714 skyrenderlater = true;
10715 RSurf_SetupDepthAndCulling();
10716 GL_DepthMask(true);
10717 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10718 // skymasking on them, and Quake3 never did sky masking (unlike
10719 // software Quake and software Quake2), so disable the sky masking
10720 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10721 // and skymasking also looks very bad when noclipping outside the
10722 // level, so don't use it then either.
10723 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10725 R_Mesh_ResetTextureState();
10726 if (skyrendermasked)
10728 R_SetupShader_DepthOrShadow(false, false, false);
10729 // depth-only (masking)
10730 GL_ColorMask(0,0,0,0);
10731 // just to make sure that braindead drivers don't draw
10732 // anything despite that colormask...
10733 GL_BlendFunc(GL_ZERO, GL_ONE);
10734 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10735 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10739 R_SetupShader_Generic_NoTexture(false, false);
10741 GL_BlendFunc(GL_ONE, GL_ZERO);
10742 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10743 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10744 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10747 if (skyrendermasked)
10748 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10750 R_Mesh_ResetTextureState();
10751 GL_Color(1, 1, 1, 1);
10754 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10755 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10756 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10758 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10762 // render screenspace normalmap to texture
10763 GL_DepthMask(true);
10764 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10769 // bind lightmap texture
10771 // water/refraction/reflection/camera surfaces have to be handled specially
10772 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10774 int start, end, startplaneindex;
10775 for (start = 0;start < texturenumsurfaces;start = end)
10777 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10778 if(startplaneindex < 0)
10780 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10781 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10785 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10787 // now that we have a batch using the same planeindex, render it
10788 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10790 // render water or distortion background
10791 GL_DepthMask(true);
10792 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);
10794 // blend surface on top
10795 GL_DepthMask(false);
10796 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10799 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10801 // render surface with reflection texture as input
10802 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10803 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);
10810 // render surface batch normally
10811 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10812 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);
10816 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10818 // OpenGL 1.3 path - anything not completely ancient
10819 qboolean applycolor;
10822 const texturelayer_t *layer;
10823 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);
10824 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10826 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10829 int layertexrgbscale;
10830 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10832 if (layerindex == 0)
10833 GL_AlphaTest(true);
10836 GL_AlphaTest(false);
10837 GL_DepthFunc(GL_EQUAL);
10840 GL_DepthMask(layer->depthmask && writedepth);
10841 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10842 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10844 layertexrgbscale = 4;
10845 VectorScale(layer->color, 0.25f, layercolor);
10847 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10849 layertexrgbscale = 2;
10850 VectorScale(layer->color, 0.5f, layercolor);
10854 layertexrgbscale = 1;
10855 VectorScale(layer->color, 1.0f, layercolor);
10857 layercolor[3] = layer->color[3];
10858 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10859 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10860 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10861 switch (layer->type)
10863 case TEXTURELAYERTYPE_LITTEXTURE:
10864 // single-pass lightmapped texture with 2x rgbscale
10865 R_Mesh_TexBind(0, r_texture_white);
10866 R_Mesh_TexMatrix(0, NULL);
10867 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10868 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10869 R_Mesh_TexBind(1, layer->texture);
10870 R_Mesh_TexMatrix(1, &layer->texmatrix);
10871 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10872 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10873 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10874 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10875 else if (FAKELIGHT_ENABLED)
10876 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10877 else if (rsurface.uselightmaptexture)
10878 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10880 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10882 case TEXTURELAYERTYPE_TEXTURE:
10883 // singletexture unlit texture with transparency support
10884 R_Mesh_TexBind(0, layer->texture);
10885 R_Mesh_TexMatrix(0, &layer->texmatrix);
10886 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10887 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10888 R_Mesh_TexBind(1, 0);
10889 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10890 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10892 case TEXTURELAYERTYPE_FOG:
10893 // singletexture fogging
10894 if (layer->texture)
10896 R_Mesh_TexBind(0, layer->texture);
10897 R_Mesh_TexMatrix(0, &layer->texmatrix);
10898 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10899 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10903 R_Mesh_TexBind(0, 0);
10904 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10906 R_Mesh_TexBind(1, 0);
10907 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10908 // generate a color array for the fog pass
10909 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10910 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10914 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10917 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10919 GL_DepthFunc(GL_LEQUAL);
10920 GL_AlphaTest(false);
10924 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10926 // OpenGL 1.1 - crusty old voodoo path
10929 const texturelayer_t *layer;
10930 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);
10931 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10933 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10935 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10937 if (layerindex == 0)
10938 GL_AlphaTest(true);
10941 GL_AlphaTest(false);
10942 GL_DepthFunc(GL_EQUAL);
10945 GL_DepthMask(layer->depthmask && writedepth);
10946 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10947 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10948 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10949 switch (layer->type)
10951 case TEXTURELAYERTYPE_LITTEXTURE:
10952 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10954 // two-pass lit texture with 2x rgbscale
10955 // first the lightmap pass
10956 R_Mesh_TexBind(0, r_texture_white);
10957 R_Mesh_TexMatrix(0, NULL);
10958 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10959 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10960 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10961 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10962 else if (FAKELIGHT_ENABLED)
10963 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10964 else if (rsurface.uselightmaptexture)
10965 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10967 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10968 // then apply the texture to it
10969 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10970 R_Mesh_TexBind(0, layer->texture);
10971 R_Mesh_TexMatrix(0, &layer->texmatrix);
10972 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10973 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10974 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);
10978 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10979 R_Mesh_TexBind(0, layer->texture);
10980 R_Mesh_TexMatrix(0, &layer->texmatrix);
10981 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10982 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10983 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10984 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);
10985 else if (FAKELIGHT_ENABLED)
10986 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);
10988 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);
10991 case TEXTURELAYERTYPE_TEXTURE:
10992 // singletexture unlit texture with transparency support
10993 R_Mesh_TexBind(0, layer->texture);
10994 R_Mesh_TexMatrix(0, &layer->texmatrix);
10995 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10996 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10997 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);
10999 case TEXTURELAYERTYPE_FOG:
11000 // singletexture fogging
11001 if (layer->texture)
11003 R_Mesh_TexBind(0, layer->texture);
11004 R_Mesh_TexMatrix(0, &layer->texmatrix);
11005 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11006 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11010 R_Mesh_TexBind(0, 0);
11011 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11013 // generate a color array for the fog pass
11014 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11015 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11019 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11022 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11024 GL_DepthFunc(GL_LEQUAL);
11025 GL_AlphaTest(false);
11029 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11033 r_vertexgeneric_t *batchvertex;
11036 // R_Mesh_ResetTextureState();
11037 R_SetupShader_Generic_NoTexture(false, false);
11039 if(rsurface.texture && rsurface.texture->currentskinframe)
11041 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11042 c[3] *= rsurface.texture->currentalpha;
11052 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11054 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11055 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11056 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11059 // brighten it up (as texture value 127 means "unlit")
11060 c[0] *= 2 * r_refdef.view.colorscale;
11061 c[1] *= 2 * r_refdef.view.colorscale;
11062 c[2] *= 2 * r_refdef.view.colorscale;
11064 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11065 c[3] *= r_wateralpha.value;
11067 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11069 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11070 GL_DepthMask(false);
11072 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11074 GL_BlendFunc(GL_ONE, GL_ONE);
11075 GL_DepthMask(false);
11077 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11079 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11080 GL_DepthMask(false);
11082 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11084 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11085 GL_DepthMask(false);
11089 GL_BlendFunc(GL_ONE, GL_ZERO);
11090 GL_DepthMask(writedepth);
11093 if (r_showsurfaces.integer == 3)
11095 rsurface.passcolor4f = NULL;
11097 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11099 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11101 rsurface.passcolor4f = NULL;
11102 rsurface.passcolor4f_vertexbuffer = 0;
11103 rsurface.passcolor4f_bufferoffset = 0;
11105 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11107 qboolean applycolor = true;
11110 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11112 r_refdef.lightmapintensity = 1;
11113 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11114 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11116 else if (FAKELIGHT_ENABLED)
11118 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11120 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11121 RSurf_DrawBatch_GL11_ApplyFakeLight();
11122 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11126 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11128 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11129 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11130 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11133 if(!rsurface.passcolor4f)
11134 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11136 RSurf_DrawBatch_GL11_ApplyAmbient();
11137 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11138 if(r_refdef.fogenabled)
11139 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11140 RSurf_DrawBatch_GL11_ClampColor();
11142 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11143 R_SetupShader_Generic_NoTexture(false, false);
11146 else if (!r_refdef.view.showdebug)
11148 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11149 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11150 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11152 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11153 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11155 R_Mesh_PrepareVertices_Generic_Unlock();
11158 else if (r_showsurfaces.integer == 4)
11160 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11161 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11162 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11164 unsigned char d = (vi << 3) * (1.0f / 256.0f);
11165 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11166 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11168 R_Mesh_PrepareVertices_Generic_Unlock();
11171 else if (r_showsurfaces.integer == 2)
11174 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11175 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11176 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11178 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11179 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11180 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11181 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11182 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11183 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11184 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11186 R_Mesh_PrepareVertices_Generic_Unlock();
11187 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11191 int texturesurfaceindex;
11193 const msurface_t *surface;
11194 float surfacecolor4f[4];
11195 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11196 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11198 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11200 surface = texturesurfacelist[texturesurfaceindex];
11201 k = (int)(((size_t)surface) / sizeof(msurface_t));
11202 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11203 for (j = 0;j < surface->num_vertices;j++)
11205 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11206 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11210 R_Mesh_PrepareVertices_Generic_Unlock();
11215 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11218 RSurf_SetupDepthAndCulling();
11219 if (r_showsurfaces.integer)
11221 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11224 switch (vid.renderpath)
11226 case RENDERPATH_GL20:
11227 case RENDERPATH_D3D9:
11228 case RENDERPATH_D3D10:
11229 case RENDERPATH_D3D11:
11230 case RENDERPATH_SOFT:
11231 case RENDERPATH_GLES2:
11232 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11234 case RENDERPATH_GL13:
11235 case RENDERPATH_GLES1:
11236 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11238 case RENDERPATH_GL11:
11239 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11245 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11248 RSurf_SetupDepthAndCulling();
11249 if (r_showsurfaces.integer)
11251 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11254 switch (vid.renderpath)
11256 case RENDERPATH_GL20:
11257 case RENDERPATH_D3D9:
11258 case RENDERPATH_D3D10:
11259 case RENDERPATH_D3D11:
11260 case RENDERPATH_SOFT:
11261 case RENDERPATH_GLES2:
11262 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11264 case RENDERPATH_GL13:
11265 case RENDERPATH_GLES1:
11266 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11268 case RENDERPATH_GL11:
11269 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11275 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11278 int texturenumsurfaces, endsurface;
11279 texture_t *texture;
11280 const msurface_t *surface;
11281 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11283 // if the model is static it doesn't matter what value we give for
11284 // wantnormals and wanttangents, so this logic uses only rules applicable
11285 // to a model, knowing that they are meaningless otherwise
11286 if (ent == r_refdef.scene.worldentity)
11287 RSurf_ActiveWorldEntity();
11288 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11289 RSurf_ActiveModelEntity(ent, false, false, false);
11292 switch (vid.renderpath)
11294 case RENDERPATH_GL20:
11295 case RENDERPATH_D3D9:
11296 case RENDERPATH_D3D10:
11297 case RENDERPATH_D3D11:
11298 case RENDERPATH_SOFT:
11299 case RENDERPATH_GLES2:
11300 RSurf_ActiveModelEntity(ent, true, true, false);
11302 case RENDERPATH_GL11:
11303 case RENDERPATH_GL13:
11304 case RENDERPATH_GLES1:
11305 RSurf_ActiveModelEntity(ent, true, false, false);
11310 if (r_transparentdepthmasking.integer)
11312 qboolean setup = false;
11313 for (i = 0;i < numsurfaces;i = j)
11316 surface = rsurface.modelsurfaces + surfacelist[i];
11317 texture = surface->texture;
11318 rsurface.texture = R_GetCurrentTexture(texture);
11319 rsurface.lightmaptexture = NULL;
11320 rsurface.deluxemaptexture = NULL;
11321 rsurface.uselightmaptexture = false;
11322 // scan ahead until we find a different texture
11323 endsurface = min(i + 1024, numsurfaces);
11324 texturenumsurfaces = 0;
11325 texturesurfacelist[texturenumsurfaces++] = surface;
11326 for (;j < endsurface;j++)
11328 surface = rsurface.modelsurfaces + surfacelist[j];
11329 if (texture != surface->texture)
11331 texturesurfacelist[texturenumsurfaces++] = surface;
11333 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11335 // render the range of surfaces as depth
11339 GL_ColorMask(0,0,0,0);
11341 GL_DepthTest(true);
11342 GL_BlendFunc(GL_ONE, GL_ZERO);
11343 GL_DepthMask(true);
11344 // R_Mesh_ResetTextureState();
11346 RSurf_SetupDepthAndCulling();
11347 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11348 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11349 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11353 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11356 for (i = 0;i < numsurfaces;i = j)
11359 surface = rsurface.modelsurfaces + surfacelist[i];
11360 texture = surface->texture;
11361 rsurface.texture = R_GetCurrentTexture(texture);
11362 // scan ahead until we find a different texture
11363 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11364 texturenumsurfaces = 0;
11365 texturesurfacelist[texturenumsurfaces++] = surface;
11366 if(FAKELIGHT_ENABLED)
11368 rsurface.lightmaptexture = NULL;
11369 rsurface.deluxemaptexture = NULL;
11370 rsurface.uselightmaptexture = false;
11371 for (;j < endsurface;j++)
11373 surface = rsurface.modelsurfaces + surfacelist[j];
11374 if (texture != surface->texture)
11376 texturesurfacelist[texturenumsurfaces++] = surface;
11381 rsurface.lightmaptexture = surface->lightmaptexture;
11382 rsurface.deluxemaptexture = surface->deluxemaptexture;
11383 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11384 for (;j < endsurface;j++)
11386 surface = rsurface.modelsurfaces + surfacelist[j];
11387 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11389 texturesurfacelist[texturenumsurfaces++] = surface;
11392 // render the range of surfaces
11393 if (ent == r_refdef.scene.worldentity)
11394 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11396 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11398 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11401 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11403 // transparent surfaces get pushed off into the transparent queue
11404 int surfacelistindex;
11405 const msurface_t *surface;
11406 vec3_t tempcenter, center;
11407 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11409 surface = texturesurfacelist[surfacelistindex];
11410 if (r_transparent_sortsurfacesbynearest.integer)
11412 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11413 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11414 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11418 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11419 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11420 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11422 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11423 if (rsurface.entity->transparent_offset) // transparent offset
11425 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11426 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11427 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11429 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);
11433 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11435 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11437 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11439 RSurf_SetupDepthAndCulling();
11440 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11441 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11442 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11446 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11450 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11453 if (!rsurface.texture->currentnumlayers)
11455 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11456 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11458 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11460 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11461 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11462 else if (!rsurface.texture->currentnumlayers)
11464 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11466 // in the deferred case, transparent surfaces were queued during prepass
11467 if (!r_shadow_usingdeferredprepass)
11468 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11472 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11473 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11478 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11481 texture_t *texture;
11482 R_FrameData_SetMark();
11483 // break the surface list down into batches by texture and use of lightmapping
11484 for (i = 0;i < numsurfaces;i = j)
11487 // texture is the base texture pointer, rsurface.texture is the
11488 // current frame/skin the texture is directing us to use (for example
11489 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11490 // use skin 1 instead)
11491 texture = surfacelist[i]->texture;
11492 rsurface.texture = R_GetCurrentTexture(texture);
11493 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11495 // if this texture is not the kind we want, skip ahead to the next one
11496 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11500 if(FAKELIGHT_ENABLED || depthonly || prepass)
11502 rsurface.lightmaptexture = NULL;
11503 rsurface.deluxemaptexture = NULL;
11504 rsurface.uselightmaptexture = false;
11505 // simply scan ahead until we find a different texture or lightmap state
11506 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11511 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11512 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11513 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11514 // simply scan ahead until we find a different texture or lightmap state
11515 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11518 // render the range of surfaces
11519 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11521 R_FrameData_ReturnToMark();
11524 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11528 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11531 if (!rsurface.texture->currentnumlayers)
11533 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11534 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11536 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11538 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11539 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11540 else if (!rsurface.texture->currentnumlayers)
11542 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11544 // in the deferred case, transparent surfaces were queued during prepass
11545 if (!r_shadow_usingdeferredprepass)
11546 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11550 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11551 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11556 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11559 texture_t *texture;
11560 R_FrameData_SetMark();
11561 // break the surface list down into batches by texture and use of lightmapping
11562 for (i = 0;i < numsurfaces;i = j)
11565 // texture is the base texture pointer, rsurface.texture is the
11566 // current frame/skin the texture is directing us to use (for example
11567 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11568 // use skin 1 instead)
11569 texture = surfacelist[i]->texture;
11570 rsurface.texture = R_GetCurrentTexture(texture);
11571 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11573 // if this texture is not the kind we want, skip ahead to the next one
11574 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11578 if(FAKELIGHT_ENABLED || depthonly || prepass)
11580 rsurface.lightmaptexture = NULL;
11581 rsurface.deluxemaptexture = NULL;
11582 rsurface.uselightmaptexture = false;
11583 // simply scan ahead until we find a different texture or lightmap state
11584 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11589 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11590 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11591 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11592 // simply scan ahead until we find a different texture or lightmap state
11593 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11596 // render the range of surfaces
11597 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11599 R_FrameData_ReturnToMark();
11602 float locboxvertex3f[6*4*3] =
11604 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11605 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11606 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11607 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11608 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11609 1,0,0, 0,0,0, 0,1,0, 1,1,0
11612 unsigned short locboxelements[6*2*3] =
11617 12,13,14, 12,14,15,
11618 16,17,18, 16,18,19,
11622 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11625 cl_locnode_t *loc = (cl_locnode_t *)ent;
11627 float vertex3f[6*4*3];
11629 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11630 GL_DepthMask(false);
11631 GL_DepthRange(0, 1);
11632 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11633 GL_DepthTest(true);
11634 GL_CullFace(GL_NONE);
11635 R_EntityMatrix(&identitymatrix);
11637 // R_Mesh_ResetTextureState();
11639 i = surfacelist[0];
11640 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11641 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11642 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11643 surfacelist[0] < 0 ? 0.5f : 0.125f);
11645 if (VectorCompare(loc->mins, loc->maxs))
11647 VectorSet(size, 2, 2, 2);
11648 VectorMA(loc->mins, -0.5f, size, mins);
11652 VectorCopy(loc->mins, mins);
11653 VectorSubtract(loc->maxs, loc->mins, size);
11656 for (i = 0;i < 6*4*3;)
11657 for (j = 0;j < 3;j++, i++)
11658 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11660 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11661 R_SetupShader_Generic_NoTexture(false, false);
11662 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11665 void R_DrawLocs(void)
11668 cl_locnode_t *loc, *nearestloc;
11670 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11671 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11673 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11674 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11678 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11680 if (decalsystem->decals)
11681 Mem_Free(decalsystem->decals);
11682 memset(decalsystem, 0, sizeof(*decalsystem));
11685 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, unsigned int decalsequence)
11688 tridecal_t *decals;
11691 // expand or initialize the system
11692 if (decalsystem->maxdecals <= decalsystem->numdecals)
11694 decalsystem_t old = *decalsystem;
11695 qboolean useshortelements;
11696 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11697 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11698 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)));
11699 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11700 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11701 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11702 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11703 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11704 if (decalsystem->numdecals)
11705 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11707 Mem_Free(old.decals);
11708 for (i = 0;i < decalsystem->maxdecals*3;i++)
11709 decalsystem->element3i[i] = i;
11710 if (useshortelements)
11711 for (i = 0;i < decalsystem->maxdecals*3;i++)
11712 decalsystem->element3s[i] = i;
11715 // grab a decal and search for another free slot for the next one
11716 decals = decalsystem->decals;
11717 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11718 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11720 decalsystem->freedecal = i;
11721 if (decalsystem->numdecals <= i)
11722 decalsystem->numdecals = i + 1;
11724 // initialize the decal
11726 decal->triangleindex = triangleindex;
11727 decal->surfaceindex = surfaceindex;
11728 decal->decalsequence = decalsequence;
11729 decal->color4f[0][0] = c0[0];
11730 decal->color4f[0][1] = c0[1];
11731 decal->color4f[0][2] = c0[2];
11732 decal->color4f[0][3] = 1;
11733 decal->color4f[1][0] = c1[0];
11734 decal->color4f[1][1] = c1[1];
11735 decal->color4f[1][2] = c1[2];
11736 decal->color4f[1][3] = 1;
11737 decal->color4f[2][0] = c2[0];
11738 decal->color4f[2][1] = c2[1];
11739 decal->color4f[2][2] = c2[2];
11740 decal->color4f[2][3] = 1;
11741 decal->vertex3f[0][0] = v0[0];
11742 decal->vertex3f[0][1] = v0[1];
11743 decal->vertex3f[0][2] = v0[2];
11744 decal->vertex3f[1][0] = v1[0];
11745 decal->vertex3f[1][1] = v1[1];
11746 decal->vertex3f[1][2] = v1[2];
11747 decal->vertex3f[2][0] = v2[0];
11748 decal->vertex3f[2][1] = v2[1];
11749 decal->vertex3f[2][2] = v2[2];
11750 decal->texcoord2f[0][0] = t0[0];
11751 decal->texcoord2f[0][1] = t0[1];
11752 decal->texcoord2f[1][0] = t1[0];
11753 decal->texcoord2f[1][1] = t1[1];
11754 decal->texcoord2f[2][0] = t2[0];
11755 decal->texcoord2f[2][1] = t2[1];
11756 TriangleNormal(v0, v1, v2, decal->plane);
11757 VectorNormalize(decal->plane);
11758 decal->plane[3] = DotProduct(v0, decal->plane);
11761 extern cvar_t cl_decals_bias;
11762 extern cvar_t cl_decals_models;
11763 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11764 // baseparms, parms, temps
11765 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, unsigned int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11770 const float *vertex3f;
11771 const float *normal3f;
11773 float points[2][9][3];
11780 e = rsurface.modelelement3i + 3*triangleindex;
11782 vertex3f = rsurface.modelvertex3f;
11783 normal3f = rsurface.modelnormal3f;
11787 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11789 index = 3*e[cornerindex];
11790 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11795 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11797 index = 3*e[cornerindex];
11798 VectorCopy(vertex3f + index, v[cornerindex]);
11803 //TriangleNormal(v[0], v[1], v[2], normal);
11804 //if (DotProduct(normal, localnormal) < 0.0f)
11806 // clip by each of the box planes formed from the projection matrix
11807 // if anything survives, we emit the decal
11808 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]);
11811 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]);
11814 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]);
11817 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]);
11820 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]);
11823 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]);
11826 // some part of the triangle survived, so we have to accept it...
11829 // dynamic always uses the original triangle
11831 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11833 index = 3*e[cornerindex];
11834 VectorCopy(vertex3f + index, v[cornerindex]);
11837 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11839 // convert vertex positions to texcoords
11840 Matrix4x4_Transform(projection, v[cornerindex], temp);
11841 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11842 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11843 // calculate distance fade from the projection origin
11844 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11845 f = bound(0.0f, f, 1.0f);
11846 c[cornerindex][0] = r * f;
11847 c[cornerindex][1] = g * f;
11848 c[cornerindex][2] = b * f;
11849 c[cornerindex][3] = 1.0f;
11850 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11853 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);
11855 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11856 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);
11858 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, unsigned int decalsequence)
11860 matrix4x4_t projection;
11861 decalsystem_t *decalsystem;
11864 const msurface_t *surface;
11865 const msurface_t *surfaces;
11866 const int *surfacelist;
11867 const texture_t *texture;
11869 int numsurfacelist;
11870 int surfacelistindex;
11873 float localorigin[3];
11874 float localnormal[3];
11875 float localmins[3];
11876 float localmaxs[3];
11879 float planes[6][4];
11882 int bih_triangles_count;
11883 int bih_triangles[256];
11884 int bih_surfaces[256];
11886 decalsystem = &ent->decalsystem;
11887 model = ent->model;
11888 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11890 R_DecalSystem_Reset(&ent->decalsystem);
11894 if (!model->brush.data_leafs && !cl_decals_models.integer)
11896 if (decalsystem->model)
11897 R_DecalSystem_Reset(decalsystem);
11901 if (decalsystem->model != model)
11902 R_DecalSystem_Reset(decalsystem);
11903 decalsystem->model = model;
11905 RSurf_ActiveModelEntity(ent, true, false, false);
11907 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11908 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11909 VectorNormalize(localnormal);
11910 localsize = worldsize*rsurface.inversematrixscale;
11911 localmins[0] = localorigin[0] - localsize;
11912 localmins[1] = localorigin[1] - localsize;
11913 localmins[2] = localorigin[2] - localsize;
11914 localmaxs[0] = localorigin[0] + localsize;
11915 localmaxs[1] = localorigin[1] + localsize;
11916 localmaxs[2] = localorigin[2] + localsize;
11918 //VectorCopy(localnormal, planes[4]);
11919 //VectorVectors(planes[4], planes[2], planes[0]);
11920 AnglesFromVectors(angles, localnormal, NULL, false);
11921 AngleVectors(angles, planes[0], planes[2], planes[4]);
11922 VectorNegate(planes[0], planes[1]);
11923 VectorNegate(planes[2], planes[3]);
11924 VectorNegate(planes[4], planes[5]);
11925 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11926 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11927 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11928 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11929 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11930 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11935 matrix4x4_t forwardprojection;
11936 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11937 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11942 float projectionvector[4][3];
11943 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11944 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11945 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11946 projectionvector[0][0] = planes[0][0] * ilocalsize;
11947 projectionvector[0][1] = planes[1][0] * ilocalsize;
11948 projectionvector[0][2] = planes[2][0] * ilocalsize;
11949 projectionvector[1][0] = planes[0][1] * ilocalsize;
11950 projectionvector[1][1] = planes[1][1] * ilocalsize;
11951 projectionvector[1][2] = planes[2][1] * ilocalsize;
11952 projectionvector[2][0] = planes[0][2] * ilocalsize;
11953 projectionvector[2][1] = planes[1][2] * ilocalsize;
11954 projectionvector[2][2] = planes[2][2] * ilocalsize;
11955 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11956 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11957 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11958 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11962 dynamic = model->surfmesh.isanimated;
11963 numsurfacelist = model->nummodelsurfaces;
11964 surfacelist = model->sortedmodelsurfaces;
11965 surfaces = model->data_surfaces;
11968 bih_triangles_count = -1;
11971 if(model->render_bih.numleafs)
11972 bih = &model->render_bih;
11973 else if(model->collision_bih.numleafs)
11974 bih = &model->collision_bih;
11977 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11978 if(bih_triangles_count == 0)
11980 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11982 if(bih_triangles_count > 0)
11984 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11986 surfaceindex = bih_surfaces[triangleindex];
11987 surface = surfaces + surfaceindex;
11988 texture = surface->texture;
11989 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11991 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11993 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11998 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12000 surfaceindex = surfacelist[surfacelistindex];
12001 surface = surfaces + surfaceindex;
12002 // check cull box first because it rejects more than any other check
12003 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12005 // skip transparent surfaces
12006 texture = surface->texture;
12007 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12009 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12011 numtriangles = surface->num_triangles;
12012 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12013 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12018 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12019 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, unsigned int decalsequence)
12021 int renderentityindex;
12022 float worldmins[3];
12023 float worldmaxs[3];
12024 entity_render_t *ent;
12026 if (!cl_decals_newsystem.integer)
12029 worldmins[0] = worldorigin[0] - worldsize;
12030 worldmins[1] = worldorigin[1] - worldsize;
12031 worldmins[2] = worldorigin[2] - worldsize;
12032 worldmaxs[0] = worldorigin[0] + worldsize;
12033 worldmaxs[1] = worldorigin[1] + worldsize;
12034 worldmaxs[2] = worldorigin[2] + worldsize;
12036 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12038 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12040 ent = r_refdef.scene.entities[renderentityindex];
12041 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12044 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12048 typedef struct r_decalsystem_splatqueue_s
12050 vec3_t worldorigin;
12051 vec3_t worldnormal;
12055 unsigned int decalsequence;
12057 r_decalsystem_splatqueue_t;
12059 int r_decalsystem_numqueued = 0;
12060 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12062 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)
12064 r_decalsystem_splatqueue_t *queue;
12066 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12069 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12070 VectorCopy(worldorigin, queue->worldorigin);
12071 VectorCopy(worldnormal, queue->worldnormal);
12072 Vector4Set(queue->color, r, g, b, a);
12073 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12074 queue->worldsize = worldsize;
12075 queue->decalsequence = cl.decalsequence++;
12078 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12081 r_decalsystem_splatqueue_t *queue;
12083 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12084 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);
12085 r_decalsystem_numqueued = 0;
12088 extern cvar_t cl_decals_max;
12089 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12092 decalsystem_t *decalsystem = &ent->decalsystem;
12094 unsigned int killsequence;
12099 if (!decalsystem->numdecals)
12102 if (r_showsurfaces.integer)
12105 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12107 R_DecalSystem_Reset(decalsystem);
12111 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12112 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12114 if (decalsystem->lastupdatetime)
12115 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12118 decalsystem->lastupdatetime = r_refdef.scene.time;
12119 numdecals = decalsystem->numdecals;
12121 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12123 if (decal->color4f[0][3])
12125 decal->lived += frametime;
12126 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12128 memset(decal, 0, sizeof(*decal));
12129 if (decalsystem->freedecal > i)
12130 decalsystem->freedecal = i;
12134 decal = decalsystem->decals;
12135 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12138 // collapse the array by shuffling the tail decals into the gaps
12141 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12142 decalsystem->freedecal++;
12143 if (decalsystem->freedecal == numdecals)
12145 decal[decalsystem->freedecal] = decal[--numdecals];
12148 decalsystem->numdecals = numdecals;
12150 if (numdecals <= 0)
12152 // if there are no decals left, reset decalsystem
12153 R_DecalSystem_Reset(decalsystem);
12157 extern skinframe_t *decalskinframe;
12158 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12161 decalsystem_t *decalsystem = &ent->decalsystem;
12170 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12173 numdecals = decalsystem->numdecals;
12177 if (r_showsurfaces.integer)
12180 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12182 R_DecalSystem_Reset(decalsystem);
12186 // if the model is static it doesn't matter what value we give for
12187 // wantnormals and wanttangents, so this logic uses only rules applicable
12188 // to a model, knowing that they are meaningless otherwise
12189 if (ent == r_refdef.scene.worldentity)
12190 RSurf_ActiveWorldEntity();
12192 RSurf_ActiveModelEntity(ent, false, false, false);
12194 decalsystem->lastupdatetime = r_refdef.scene.time;
12196 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12198 // update vertex positions for animated models
12199 v3f = decalsystem->vertex3f;
12200 c4f = decalsystem->color4f;
12201 t2f = decalsystem->texcoord2f;
12202 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12204 if (!decal->color4f[0][3])
12207 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12211 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12214 // update color values for fading decals
12215 if (decal->lived >= cl_decals_time.value)
12216 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12220 c4f[ 0] = decal->color4f[0][0] * alpha;
12221 c4f[ 1] = decal->color4f[0][1] * alpha;
12222 c4f[ 2] = decal->color4f[0][2] * alpha;
12224 c4f[ 4] = decal->color4f[1][0] * alpha;
12225 c4f[ 5] = decal->color4f[1][1] * alpha;
12226 c4f[ 6] = decal->color4f[1][2] * alpha;
12228 c4f[ 8] = decal->color4f[2][0] * alpha;
12229 c4f[ 9] = decal->color4f[2][1] * alpha;
12230 c4f[10] = decal->color4f[2][2] * alpha;
12233 t2f[0] = decal->texcoord2f[0][0];
12234 t2f[1] = decal->texcoord2f[0][1];
12235 t2f[2] = decal->texcoord2f[1][0];
12236 t2f[3] = decal->texcoord2f[1][1];
12237 t2f[4] = decal->texcoord2f[2][0];
12238 t2f[5] = decal->texcoord2f[2][1];
12240 // update vertex positions for animated models
12241 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12243 e = rsurface.modelelement3i + 3*decal->triangleindex;
12244 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12245 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12246 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12250 VectorCopy(decal->vertex3f[0], v3f);
12251 VectorCopy(decal->vertex3f[1], v3f + 3);
12252 VectorCopy(decal->vertex3f[2], v3f + 6);
12255 if (r_refdef.fogenabled)
12257 alpha = RSurf_FogVertex(v3f);
12258 VectorScale(c4f, alpha, c4f);
12259 alpha = RSurf_FogVertex(v3f + 3);
12260 VectorScale(c4f + 4, alpha, c4f + 4);
12261 alpha = RSurf_FogVertex(v3f + 6);
12262 VectorScale(c4f + 8, alpha, c4f + 8);
12273 r_refdef.stats[r_stat_drawndecals] += numtris;
12275 // now render the decals all at once
12276 // (this assumes they all use one particle font texture!)
12277 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);
12278 // R_Mesh_ResetTextureState();
12279 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12280 GL_DepthMask(false);
12281 GL_DepthRange(0, 1);
12282 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12283 GL_DepthTest(true);
12284 GL_CullFace(GL_NONE);
12285 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12286 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12287 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12291 static void R_DrawModelDecals(void)
12295 // fade faster when there are too many decals
12296 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12297 for (i = 0;i < r_refdef.scene.numentities;i++)
12298 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12300 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12301 for (i = 0;i < r_refdef.scene.numentities;i++)
12302 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12303 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12305 R_DecalSystem_ApplySplatEntitiesQueue();
12307 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12308 for (i = 0;i < r_refdef.scene.numentities;i++)
12309 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12311 r_refdef.stats[r_stat_totaldecals] += numdecals;
12313 if (r_showsurfaces.integer)
12316 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12318 for (i = 0;i < r_refdef.scene.numentities;i++)
12320 if (!r_refdef.viewcache.entityvisible[i])
12322 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12323 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12327 extern cvar_t mod_collision_bih;
12328 static void R_DrawDebugModel(void)
12330 entity_render_t *ent = rsurface.entity;
12331 int i, j, flagsmask;
12332 const msurface_t *surface;
12333 dp_model_t *model = ent->model;
12335 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12338 if (r_showoverdraw.value > 0)
12340 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12341 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12342 R_SetupShader_Generic_NoTexture(false, false);
12343 GL_DepthTest(false);
12344 GL_DepthMask(false);
12345 GL_DepthRange(0, 1);
12346 GL_BlendFunc(GL_ONE, GL_ONE);
12347 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12349 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12351 rsurface.texture = R_GetCurrentTexture(surface->texture);
12352 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12354 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12355 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12356 if (!rsurface.texture->currentlayers->depthmask)
12357 GL_Color(c, 0, 0, 1.0f);
12358 else if (ent == r_refdef.scene.worldentity)
12359 GL_Color(c, c, c, 1.0f);
12361 GL_Color(0, c, 0, 1.0f);
12362 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12366 rsurface.texture = NULL;
12369 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12371 // R_Mesh_ResetTextureState();
12372 R_SetupShader_Generic_NoTexture(false, false);
12373 GL_DepthRange(0, 1);
12374 GL_DepthTest(!r_showdisabledepthtest.integer);
12375 GL_DepthMask(false);
12376 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12378 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12382 qboolean cullbox = false;
12383 const q3mbrush_t *brush;
12384 const bih_t *bih = &model->collision_bih;
12385 const bih_leaf_t *bihleaf;
12386 float vertex3f[3][3];
12387 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12388 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12390 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12392 switch (bihleaf->type)
12395 brush = model->brush.data_brushes + bihleaf->itemindex;
12396 if (brush->colbrushf && brush->colbrushf->numtriangles)
12398 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);
12399 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12400 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12403 case BIH_COLLISIONTRIANGLE:
12404 triangleindex = bihleaf->itemindex;
12405 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12406 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12407 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12408 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);
12409 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12410 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12412 case BIH_RENDERTRIANGLE:
12413 triangleindex = bihleaf->itemindex;
12414 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12415 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12416 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12417 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);
12418 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12419 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12425 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12428 if (r_showtris.integer && qglPolygonMode)
12430 if (r_showdisabledepthtest.integer)
12432 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12433 GL_DepthMask(false);
12437 GL_BlendFunc(GL_ONE, GL_ZERO);
12438 GL_DepthMask(true);
12440 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12441 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12443 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12445 rsurface.texture = R_GetCurrentTexture(surface->texture);
12446 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12448 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12449 if (!rsurface.texture->currentlayers->depthmask)
12450 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12451 else if (ent == r_refdef.scene.worldentity)
12452 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12454 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12455 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12459 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12460 rsurface.texture = NULL;
12463 if (r_shownormals.value != 0 && qglBegin)
12467 if (r_showdisabledepthtest.integer)
12469 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12470 GL_DepthMask(false);
12474 GL_BlendFunc(GL_ONE, GL_ZERO);
12475 GL_DepthMask(true);
12477 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12479 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12481 rsurface.texture = R_GetCurrentTexture(surface->texture);
12482 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12484 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12485 qglBegin(GL_LINES);
12486 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12488 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12490 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12491 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12492 qglVertex3f(v[0], v[1], v[2]);
12493 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12494 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12495 qglVertex3f(v[0], v[1], v[2]);
12498 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12500 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12502 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12503 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12504 qglVertex3f(v[0], v[1], v[2]);
12505 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12506 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12507 qglVertex3f(v[0], v[1], v[2]);
12510 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12512 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12514 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12515 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12516 qglVertex3f(v[0], v[1], v[2]);
12517 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12518 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12519 qglVertex3f(v[0], v[1], v[2]);
12522 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12524 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12526 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12527 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12528 qglVertex3f(v[0], v[1], v[2]);
12529 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12530 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12531 qglVertex3f(v[0], v[1], v[2]);
12538 rsurface.texture = NULL;
12543 int r_maxsurfacelist = 0;
12544 const msurface_t **r_surfacelist = NULL;
12545 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12547 int i, j, endj, flagsmask;
12548 dp_model_t *model = r_refdef.scene.worldmodel;
12549 msurface_t *surfaces;
12550 unsigned char *update;
12551 int numsurfacelist = 0;
12555 if (r_maxsurfacelist < model->num_surfaces)
12557 r_maxsurfacelist = model->num_surfaces;
12559 Mem_Free((msurface_t**)r_surfacelist);
12560 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12563 RSurf_ActiveWorldEntity();
12565 surfaces = model->data_surfaces;
12566 update = model->brushq1.lightmapupdateflags;
12568 // update light styles on this submodel
12569 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12571 model_brush_lightstyleinfo_t *style;
12572 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12574 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12576 int *list = style->surfacelist;
12577 style->value = r_refdef.scene.lightstylevalue[style->style];
12578 for (j = 0;j < style->numsurfaces;j++)
12579 update[list[j]] = true;
12584 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12588 R_DrawDebugModel();
12589 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12593 rsurface.lightmaptexture = NULL;
12594 rsurface.deluxemaptexture = NULL;
12595 rsurface.uselightmaptexture = false;
12596 rsurface.texture = NULL;
12597 rsurface.rtlight = NULL;
12598 numsurfacelist = 0;
12599 // add visible surfaces to draw list
12600 for (i = 0;i < model->nummodelsurfaces;i++)
12602 j = model->sortedmodelsurfaces[i];
12603 if (r_refdef.viewcache.world_surfacevisible[j])
12604 r_surfacelist[numsurfacelist++] = surfaces + j;
12606 // update lightmaps if needed
12607 if (model->brushq1.firstrender)
12609 model->brushq1.firstrender = false;
12610 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12612 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12616 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12617 if (r_refdef.viewcache.world_surfacevisible[j])
12619 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12621 // don't do anything if there were no surfaces
12622 if (!numsurfacelist)
12624 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12627 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12629 // add to stats if desired
12630 if (r_speeds.integer && !skysurfaces && !depthonly)
12632 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12633 for (j = 0;j < numsurfacelist;j++)
12634 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12637 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12640 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12642 int i, j, endj, flagsmask;
12643 dp_model_t *model = ent->model;
12644 msurface_t *surfaces;
12645 unsigned char *update;
12646 int numsurfacelist = 0;
12650 if (r_maxsurfacelist < model->num_surfaces)
12652 r_maxsurfacelist = model->num_surfaces;
12654 Mem_Free((msurface_t **)r_surfacelist);
12655 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12658 // if the model is static it doesn't matter what value we give for
12659 // wantnormals and wanttangents, so this logic uses only rules applicable
12660 // to a model, knowing that they are meaningless otherwise
12661 if (ent == r_refdef.scene.worldentity)
12662 RSurf_ActiveWorldEntity();
12663 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12664 RSurf_ActiveModelEntity(ent, false, false, false);
12666 RSurf_ActiveModelEntity(ent, true, true, true);
12667 else if (depthonly)
12669 switch (vid.renderpath)
12671 case RENDERPATH_GL20:
12672 case RENDERPATH_D3D9:
12673 case RENDERPATH_D3D10:
12674 case RENDERPATH_D3D11:
12675 case RENDERPATH_SOFT:
12676 case RENDERPATH_GLES2:
12677 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12679 case RENDERPATH_GL11:
12680 case RENDERPATH_GL13:
12681 case RENDERPATH_GLES1:
12682 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12688 switch (vid.renderpath)
12690 case RENDERPATH_GL20:
12691 case RENDERPATH_D3D9:
12692 case RENDERPATH_D3D10:
12693 case RENDERPATH_D3D11:
12694 case RENDERPATH_SOFT:
12695 case RENDERPATH_GLES2:
12696 RSurf_ActiveModelEntity(ent, true, true, false);
12698 case RENDERPATH_GL11:
12699 case RENDERPATH_GL13:
12700 case RENDERPATH_GLES1:
12701 RSurf_ActiveModelEntity(ent, true, false, false);
12706 surfaces = model->data_surfaces;
12707 update = model->brushq1.lightmapupdateflags;
12709 // update light styles
12710 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12712 model_brush_lightstyleinfo_t *style;
12713 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12715 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12717 int *list = style->surfacelist;
12718 style->value = r_refdef.scene.lightstylevalue[style->style];
12719 for (j = 0;j < style->numsurfaces;j++)
12720 update[list[j]] = true;
12725 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12729 R_DrawDebugModel();
12730 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12734 rsurface.lightmaptexture = NULL;
12735 rsurface.deluxemaptexture = NULL;
12736 rsurface.uselightmaptexture = false;
12737 rsurface.texture = NULL;
12738 rsurface.rtlight = NULL;
12739 numsurfacelist = 0;
12740 // add visible surfaces to draw list
12741 for (i = 0;i < model->nummodelsurfaces;i++)
12742 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12743 // don't do anything if there were no surfaces
12744 if (!numsurfacelist)
12746 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12749 // update lightmaps if needed
12753 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12758 R_BuildLightMap(ent, surfaces + j);
12763 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12765 // add to stats if desired
12766 if (r_speeds.integer && !skysurfaces && !depthonly)
12768 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12769 for (j = 0;j < numsurfacelist;j++)
12770 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12773 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12776 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12778 static texture_t texture;
12779 static msurface_t surface;
12780 const msurface_t *surfacelist = &surface;
12782 // fake enough texture and surface state to render this geometry
12784 texture.update_lastrenderframe = -1; // regenerate this texture
12785 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12786 texture.basealpha = 1.0f;
12787 texture.currentskinframe = skinframe;
12788 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12789 texture.offsetmapping = OFFSETMAPPING_OFF;
12790 texture.offsetscale = 1;
12791 texture.specularscalemod = 1;
12792 texture.specularpowermod = 1;
12793 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12794 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12795 // JUST GREP FOR "specularscalemod = 1".
12797 surface.texture = &texture;
12798 surface.num_triangles = numtriangles;
12799 surface.num_firsttriangle = firsttriangle;
12800 surface.num_vertices = numvertices;
12801 surface.num_firstvertex = firstvertex;
12804 rsurface.texture = R_GetCurrentTexture(surface.texture);
12805 rsurface.lightmaptexture = NULL;
12806 rsurface.deluxemaptexture = NULL;
12807 rsurface.uselightmaptexture = false;
12808 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12811 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)
12813 static msurface_t surface;
12814 const msurface_t *surfacelist = &surface;
12816 // fake enough texture and surface state to render this geometry
12817 surface.texture = texture;
12818 surface.num_triangles = numtriangles;
12819 surface.num_firsttriangle = firsttriangle;
12820 surface.num_vertices = numvertices;
12821 surface.num_firstvertex = firstvertex;
12824 rsurface.texture = R_GetCurrentTexture(surface.texture);
12825 rsurface.lightmaptexture = NULL;
12826 rsurface.deluxemaptexture = NULL;
12827 rsurface.uselightmaptexture = false;
12828 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);